Java虚拟机总结

2016-07-06  本文已影响63人  niaoge2016

本文为对《深入理解Java虚拟机》一书的简单总结,仅供个人学习使用。

JVM运行时数据区

Java虚拟机所管理的内存包括以下几个区域:

JVM运行时数据区

下面分别对它们进行简单的介绍

虚拟机对象探秘

对象创建过程

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程,加载检查之后会在堆中划分出一定的内存。
在完成new指令之后,紧接着会调用<init>方法将对象初始化,这时一个完整的对象才算创建了出来。

对象的访问

目前主流的访问方式有:使用句柄直接指针两种方式。

通过句柄访问对象 通过直接指针访问对象

使用句柄访问的最大好处是reference中存储稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,不需要更改reference本身。
使用直接指针访问方式的最大好处是速度更快,它节省了一次指针定位的时间开销。如果对象的访问在Java中非常频繁,将会节省比较可观的时间。

OutOfMemoryError错误

Java堆内存的OutOfMemoryError异常是实际应用中常见的内存溢出异常情况。当出现Java堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap space”。
当产生的对象过多时,会出现这个错误信息。解决办法:调整虚拟机堆参数(-Xmx和-Xms)。
Java方法区会存储类信息、常量、静态变量等。如果产生了大量类,比如某个ssh项目因为加载了框架和大量jar包,这样class文件都会载入内存的方法区,这样如果出现内存无法继续扩展的情况,也会出现java.lang.OutOfMemoryError,然后紧跟着PermGen space信息。通过-XX:PermSize和-XX:MaxPermSize可以限制方法区大小。

内存分配策略

垃圾回收(GC)需要完成的3件事情:

判断对象是否可回收
如上图,object5、object6、object7虽然相互有关联,但是它们到GC Roots是不可达的,所以它们被判定为可回收的对象。
在Java中,可作为GC Roots的对象包括:
虚拟机栈中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI引用的对象

垃圾收集算法

标记-清除算法
分为“标记”“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成之后统一回收所有被标记的对象。
主要不足:
①效率低下。标记和清除两个过程效率都不高。
②空间问题。产生了大量的不连续的内存碎片,导致以后产生较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。 复制算法
解决效率问题,将可用内存按照容量分为大小相等的两块,每次只使用其中的一块。当一块内存用完时,将还存活的对象复制到另外一块上面,然后把已使用过的内存空间清理掉。
存在问题:内存缩小为原来的一半,成本较高。 标记-整理算法

“标记”过程仍然和“标记-清除”算法一样,但是后续步骤改为让所有存活的对象都向一端移动,然后直接清理端边界之外的内存。

分代收集算法

内存主要被分成三块:新生代,老生代,持久代

各内存区域图解

在新生代中,每次垃圾收集都发现有大量对象死去,只有少量存活,选用复制算法
在老生代中,由于对象存活率较高,没有额外的空间进行分配担保,使用 标记-清理算法标记-整理算法

上一篇 下一篇

猜你喜欢

热点阅读