daily 2017 8 25 jvm结构及垃圾回收机制 - wtdig/study GitHub Wiki
1、一个程序的运行,首先由classFile定位类的位置,由classloader加载该类到jvm中
2、jvm的空间被划分为方法区、堆区(Heap)、java 栈区、本地方法栈区、程序计数器
3、方法区和堆区是所有线程共享的空间,其它是每个线程独享的空间。类加载到方法区后,当需要创建对象,将对象存在堆区,java栈中的每一个方法的调用都是一个栈帧
4、当创建一个类对象时,需要使用时,类才会被加载
5、haap区被分成:年轻代、老年代;年轻代分为:eden区、幸存一区、幸存二区;老年代只有一个区
6、所有对象的创建都从eden区开始,如果对象占用较大的连续空间,会直接到老年区创建;当eden区的空间满了之后,如果该对象还有引用,不能被Minro GC掉,就会进入随机选择的一个空的幸存区,当下次eden区再次满了之后,继续进入该幸存区,当幸存区满了之后,就会进入老年代,清空该幸存区;下次,eden区满了之后,就会选择另外一个幸存区,依次执行下去。在老年区满了之后或者满足某个条件,full gc就去回收该空间,如果老年区爆满的化,就会出现内存溢出的错误
7、持久代(Permanent generation)也称之为 方法区(Method area):用于保存类常量以及字符串常量。注意,这个区域不是用于存储那些从老年代存活下来的对象,这个区域也可能发生GC。发生在这个区域的GC事件也被算为 Major GC 。只不过在这个区域发生GC的条件非常严苛,必须符合以下三种条件才会被回收:
1)、所有实例被回收
2)、加载该类的ClassLoader 被回收
3)、Class 对象无法通过任何途径访问(包括反射)
可能我们会有疑问:
如果老年代的对象需要引用新生代的对象,会发生什么呢?
为了解决这个问题,老年代中存在一个 card table ,它是一个512byte大小的块。所有老年代的对象指向新生代对象的引用都会被记录在这个表中。当针对新生代执行GC的时候,只需要查询 card table 来决定是否可以被回收,而不用查询整个老年代。这个 card table 由一个write barrier 来管理。write barrier给GC带来了很大的性能提升,虽然由此可能带来一些开销,但完全是值得的。
8、gc算法
1)根搜索算法
2)标记-清除算法
3)复制算法
4)标记-整理算法
9、JVM为了优化内存的回收,使用了分代回收的方式,对于新生代内存的回收(Minor GC)主要采用复制算法。而对于老年代的回收(Major GC),大多采用标记-整理算法。
详情可以参考以下链接:
Java性能优化之JVM GC(垃圾回收机制):https://zhuanlan.zhihu.com/p/25539690
java垃圾回收以及jvm参数调优概述:https://mp.weixin.qq.com/s/NJm28LyDWFYvNDR5yU9dag