`

深入理解JVM学习笔记-自动内存管理机制

    博客分类:
  • JVM
 
阅读更多

 

运行时的数据区

 

1.线程隔离的数据区

程序计数器, 如果执行的是Native方法的时候,这个计数器的值为空。

虚拟机栈, 每个方法在执行的同时都会创建一个栈帧, 用来存储局部变量表,操作数栈,动态链接,方法出口等信息。

本地方法栈, 与虚拟机栈的作用相似,但是该栈是为Native方法服务的

 

2.由所有线程共享的数据区

java堆,java虚拟机中管理的内存中最大的一块, 几乎所有的对象实例都在这里分配内存

,该区域是垃圾回收的主要区域, java堆还可以细分为:新生代和老年代;再细致一点的话可以分为

Eden空间,From survivor空间, To survivor空间

方法区,用于存储已被虚拟机加载的类信息,常量,静态变量,即使编译器编译后的代码等

数据, 别名为non-heap, 很多人更加愿意称其为"永久代", 常量池是在这个区域的

 

对象的创建

①虚拟机要对对象进行必要的设置, eg:这个对象时哪个类的对象,如何才能找到类的元数据信息,对

象的哈希码,对象的gc分代年龄等信息。这些信息存放在对象的对象头之中

对象的内存布局

②对象在内存中存储的布局可以分为3块区域:对象头, 实例数据和对齐填充

1) 对象头:其中中包含两部分的数据 一部分用于存储对象自身的运行时的数据(大小根据虚拟机的位

数来进行确定) 另外一部分是类型指针  即对象指向它的类元数据的指针,另外如果对象是一个java数组,那在对象头中还必须有一块用于记录数组长度的数据。

2) 实例数据:对象真正存储的有效信息

3)填充部分并不是一定存在的, 对象的大小必须是8字节的整数倍

 

对象的访问( 分为对象实例数据, 对象类型数据)

①引用直接指向句柄池, 然后句柄池中的指针指向别处的对象地址  如果对象的地址发生改变,只会改变句柄的指向即可

②直接指针访问  java栈本地变量表中存储的就是一个地址了    访问的速度比较快(Hotspot使用的是该种方式)

 

java堆溢出

如果产生了堆溢出的话,可以使用内存映像分析工具进行分析

如果是内存泄露的话, 可以进一步通过工具查看泄露对象到GC root的引用链, 如果找不到的话则应

该去查看虚拟机的堆参数

 

Hotspot中不区分虚拟机栈和本地方法栈  

如果线程请求的栈深度大于虚拟机所允许的最大深度   则将抛出StackOutflowError错误

如果虚拟机在扩展栈是无法申请到足够的内存空间时, 则抛出OutOfMemoryError异常

 

虚拟机提供了参数来限制java堆和方法区这两部分内存的最大值

应为程序计数器使用的内存空间很少, 几乎可以忽略不计, 则内存除了这两部分其余剩下的空间用来

 

存放本地方法栈和虚拟机栈

 

tip:String.intern(), 此方法表示, 如果常量池中存在该字符串的话, 则返回代表池中这个字符串的String对象, 如果不存在的话, 则将这个字符串加到常量池中,返回的是此String对象的引用

1.6和1.7中String.intern()方法的区别

jdk1.6中如果字符串是首次出现, 则会将字符串复制到永久区, 然后返回相应的引用, 如果是

 

jdk1.7的话, 则只是在常量池中记录首次出现实例的引用

如果经常动态生成大量的Class的应用中, 需要特别注意类的回收状况

 

本机直接内存

如果该内存不通过参数进行限制的话, 默认和heap的最大内存一样大

 

 

 

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics