当前位置: 美高梅集团手机版 > 美高梅集团 > 正文

澳门美高梅游戏:线程执行Java方法,存储新对象

时间:2019-10-07 05:04来源:美高梅集团
“原创精选,转载注明出处,三克油”@Date 2017.05.24 概念介绍 0. 前言 JVM笔记系列,以JDK1.7为基准,主要以《深入理解Java虚拟机》(第二版)和《Java虚拟机规范(JavaSE 7版)》为参考,主要

“原创精选,转载注明出处,三克油”@Date 2017.05.24

概念介绍

0. 前言

JVM笔记系列,以JDK1.7为基准,主要以《深入理解Java虚拟机》(第二版)和《Java虚拟机规范(Java SE 7版)》 为参考,主要包括下图所示的五部分内容:1.类加载,2.内存区域,3.垃圾回收,4.JVM参数,5.JVM监控工具。

本人是Java程序员,重点关注这些有助于优化开发、性能调优、问题解决等这些和具体生产密切相关的部分;关于Class的文件结构、编译、指令等部分,可以阅读上述书籍或其它材料。

澳门美高梅游戏 1

jvm.png

本文主要记录JVM内存区域结构的相关知识,本文的主要知识点如下:

澳门美高梅游戏 2

jvm内存区域结构.png

2.1概述

讲解内存各个区域的作用、服务对象以及其中可能产生的问题

    1. 年轻代
      • Eden区
        • 存储新对象或者生命周期很短的对象
      • From Survivor区
        • Eden区的垃圾回收仍能存活下来的依旧存在引用的对象会待在这个区域
      • To Survivor区
        • Eden区的垃圾回收仍能存活下来的依旧存在引用的对象会待在这个区域
    2. 年老代
      • Eden区和Survivor区的多次GC后仍然存活下来的对象 - major GC
      • 内存大小为-Xmx对应的值减去-Xmn对应的值
      • 新建的对象也有可能直接进入老年代
        1. 大对象:可通过启动参数设置-XX:PretenureSizeThreshold超过则直接在老年代分配
        2. 大的数组对象,且数组中无引用外部对象
  • 方法区(Non-Heap

    1. 永久代(HotSpot VM)
      • 各个线程共享的内存区域
      • 方法区是线程安全的
      • 存储已被虚拟机加载的类信息、方法、常量、静态变量、即时编译器编译后的代码等数据
      • 在Java8里已被废除了,被元空间取代
    2. 运行时常量池(Runtime Constant Pool)
      • 存放编译期生成的各种字面量和符号引用
      • 运行期间也可能将新的常量放入池中
      • String类的intern()方法
    1. 虚拟机栈
      • 方法执行的内存模型
      • 每个线程都有自己专属的栈,这个栈是别的线程无法访问的
      • 生命周期与线程相同
      • 存储局部变量表(存放方法参数和方法内部定义的局部变量)、操作栈、动态链接、方法出口、方法调用的中间结果及返回地址
      • 线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
      • 虚拟机栈可动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常
    2. 本地方法栈
      • 为虚拟机使用到的Native方法服务
  • 计数器

    1. 程序计数器
      • 分支、循环、跳转、异常处理、线程恢复
      • 每条线程都需要有一个独立的程序计数器
      • JVM执行的字节码指令地址
      • 当前线程所执行的字节码的行号指示器
      • 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
      • 此内存区域是唯一一个在Java 虚拟机规范中没有规定任何OutOfMemoryError情况的区域
  • 直接内存(Direct Memory)

    1. NIO出现后使用
      • 本机直接内存的分配不会受到Java堆大小的限制

1. JVM内存区域结构

JVM定义了若干程序运行期使用到的数据区,其中一些随着JVM进程启动而创建,随着JVM退出而销毁;另一些则是与线程一一对应,随着线程的启动和结束而建立和销毁。JVM的运行时数据区分为5个部分,如下图所示,分别是程序计数器、Java栈、Native方法栈、堆、方法区。

澳门美高梅游戏 3

jvm-runtime-area.png

2.2运行时数据区

持久代 --> 元空间

1.1 程序计数器(Program Counter)

  • 程序计数器占用非常小的内存,指向下一条指令的地址。
  • 每个线程拥有一个程序计数器。
  • 程序计数器在线程创建时创建。
  • 如果是Java方法,程序计数器指向字节码指令的地址。
  • 如果是Native方法,程序计数器值则为空(Undefined)。
  • 程序计数器不会出现OutOfMemoryError。

2.2.1程序计数器

当前线程所执行的字节码的行号显示器

每个线程都有独立的程序计数器,既线程私有

线程执行Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址

线程执行Native方法,计数器值为空

唯一一个在Java虚拟机规范中没有OutOfMemoryError情况的区域

  • 元空间
    1. 本地堆内存中的一部分
    2. 达到最大阈值时进行该区域清理
    3. 类及相关的元数据的生命周期与类加载器的一致
    4. 使用-XX:MaxMetaspaceSize参数可以设置元空间的最大值
    5. 默认是没有上限的,系统内存上限是多少它就是多少
    6. 达到设定的最大值后,对于无用的类和类加载器,垃圾收集此时会触发

1.2 Java栈

  • Java栈是线程私有的,生命周期和线程相同。
  • 栈是由一系列栈帧组成的。
  • 每个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
  • 每一个方法被调用到执行完成的过程,就是一个栈帧在JVM从入栈到出栈的过程。

澳门美高梅游戏 4

jvm-stack-frame.png

JVM规范中描述,Java栈可能会出现两种异常。

  • StackOverflowError:线程请求的栈深大于虚拟机所允许的深度(例如无限递归)。
  • OutOfMemoryError:虚拟机栈可以动态扩展,如果扩展无法申请足够的内存时,就会报出。

2.2.2Java栈

线程私有,生命周期和线程相同

Java方法执行的内存模型,每个方法在执行的同时会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息,方法调用到完成的过程,对应着一个栈帧在虚拟机栈中的入栈到出栈的过程

局部变量表

编译期可知的各种数据类型

对象引用

returnAddress类型:指向一条字节码指令的地址

64位长度的long和double占两个局部变量空间

内存空间在编译器分配完成

两种异常:StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度;OutOfMemoryError:动态扩展时无法申请到足够的内存

Error

1.3 Native方法栈

本地方法栈和Java栈是非常相似的,Java栈是为了执行Java方法服务,本地方法栈是为了执行Native方法使用。在HotSpot虚拟机中,Java栈和本地方法栈合二为一。

2.2.3本地方法栈

使用native方法服务

也会抛出StackOverflowError和OutOfMemoryError

  • 内存溢出(Out Of Memory) : 程序在申请内存时,没有足够的内存空间供其使用
  • 内存泄露(Memory Leak) : 程序在申请内存后,无法释放已申请的内存空间.一次内存泄露可以忽略,泄露堆积后果很严重,最终会导致Out Of Memory.

1.4 堆(Heap)

  • Java堆是JVM所管理的内存中最大的一块,生命周期和JVM进程相同。
  • 用于存放对象实例,几乎所有的对象都在Heap上。
  • Java堆是所有线程共享的空间。

从垃圾回收的角度来说,Java堆分为新生代和老生代,其中新生代还分为Eden、From Survivor(S0)、To Survivor(S1)三部分,如下图所示。

澳门美高梅游戏 5

jvm-heap.png

默认参数下,新生代:老生代 = 1:2,Eden:Survivor = 8:1。Java堆中最大可用内存 = 老生代+ Eden + Survivor*1,即S0和S1永远有一个处于闲置的状态,GC的时JVM候会把其中一个Survivor中存活的对象复制到另一个Survivor中。

  • Eden区是Java实例对象优先分配的区域,如果Eden没有足够的空间,将会执行一次Minor GC。
  • 经过Minor GC后,Eden+S0(或者S1)中还存活的对象将会转移到S1中,然后S0会被清空。
  • Survivor中放不下的、存活次数超过一定数目的对象,会被转移到老年代(Old)空间,大对象也可能会直接分配到老年代(Old)空间。
  • 当老年代(Old)空间不够时,将会发生Major GC。
  • 如果垃圾回收后,仍然没有足够的空间,那么将会抛出OutOfMemoryError。

2.2.4 Java堆

被所有线程共享,虚拟机启动的时候创建

唯一目的是存放对象实例

垃圾收集器管理的主要区域

划分:更好的回收内存或分配内存【新生代(Eden、From Survivor、To Survivor)】【老年代】

可物理上不连续,逻辑上连续

编辑:美高梅集团 本文来源:澳门美高梅游戏:线程执行Java方法,存储新对象

关键词: