JVM细节

    xiaoxiao2021-03-25  72

    JVM内存:

    1.heap

    内存是无序的。存放对象,当内存空间不够时报错信息为OutOfMemoryError

    垃圾回收:可达性分析

          在Java中,可以作为GC Roots的对象有以下几种:

    虚拟机栈中的本地变量表中引用的对象,也就是正在执行函数体中的局部变量引用的对象。方法区中类静态属性引用的对象方法区中常量引用的对象本地方法栈中(Native方法中)引用的对象  

    判定对象可以回收:

    1.把引用赋值为null,或者把引用指向新对象

    2.局部变量执行完,生成的对象都可以被回收

    3.弱引用与其关联

    判对象死刑,2次标记:

    http://www.cnblogs.com/duke2016/p/6013519.html

    第一次标记就是筛选

    第一次标记时会进行一次筛选:筛选的条件是是否有必要执行finalize()方法。 当对象没有覆盖finalize()方法,或者finalize()被虚拟机调用过,则虚拟机认为没有必要执行finalize()方法

     如果这个对象有必要执行finalize(),则会放在一个队列里,以一个低优先级的线程进行执行finalize()方法进行二次标记,如果在finalize()方法中,对象重新回到引用链上(比如this赋值给其他引用链上的对象),则该对象不被回收,而移出该队列。     注意:finalize()方法只被调用一次,如果这个对象在GC时被调用过一次finalize()方法,则第二次GC的时候,就会被判断为没有必要执行finalize()而被直接回收。

    典型的垃圾回收算法:代码我以后看到了会补上

    1.先标记再清除,缺点是内存碎片太多

    2.复制算法:把内存分为完全相等的2块,每次只使用其中一块。当这个用完,把还活着的对象复制到另一块,这一块就全部清空。

                        优点:解决了内存碎片                 缺点:以前还能用一整块,现在能够使用的内存是原来的一半

    3.先标记再整理

      标记-整理算法,思路就是先进行垃圾内存的标记,这个和标记-清除算法中的标记阶段一样。标记-整理算法会对内存区域进行整理,将当前的所有存活的对象移动到内存的一端,清理掉边界以外的内存,这样就可以得到一块连续的空闲内存空间了。

    优点:盖住了复制算法的缺点,不会浪费一半的内存

    4.分代搜集算法

    新生代中的对象大部分的存活时间都很短,所以如果按照复制算法中的以1:1的方式来平分年轻代的话,会浪费很多内存空间。所以将年轻代划分为上图中所示的,一块较大的eden区和两块同等大小的survivor区,每次只使用eden区和其中的一块survivor区,保证了比例至少2:1,当进行内存回收的时候,会将当前存活的对象一次性复制到另一块空闲的survivor区上.

     HotSpot虚拟机默认Eden区和其中一块Survivor区的占比是8:1,通过JVM参数"-XX:SurvivorRatio"控制这个比值。SurvivorRatio的值是一个整数,表示Eden区域是一块Survivor区域的大小的几倍,所以,如果SurvivorRatio的值是8,那么Eden区和其中Survivor区的占比就是8:1,那么总的年轻代的大小就是(Eden + S0 + S1) = (8 + 1 + 1) = 10,所以年轻代每次可以使用的内存空间就是(Eden + S0) = (8 + 1)  = 9,占了整个年轻代的 9 / 10 = 90%,而每次只浪费了10%的内存空间用于复制

    http://www.cnblogs.com/duke2016/p/6013519.html

    老年代使用标记清理或者标记整理进行回收内存。

    2.stack

    后进先出。当一个线程被创建出来,这个栈也被跟着被创建出来。当线程被销毁时,栈也跟着被销毁了。方法的调用和方法的返回对应着栈帧入栈和出栈的操作。栈被线程私有,不能和其他线程使用,不存在线程安全的问题。可能的异常是stackOverflowError线程请求的栈深度超过虚拟机允许值和OutOfMemoryError

    3.Method Area

    常量,静态变量,优化后的代码

    4.pc Registers

    每个线程都有一个人pc register,是线程私有的。字节码解释器通过修改这里面的值来选择下一条要执行的指令,执行native方法,PC值为undefind

    5.Native Method Stacks

    其他语种的代码

    java对象的结构:

    1.header对象头

    对象头主要用于对内服务,也就是为JVM服务的。目的是为该对象设置附加数据,方便识别和查找。分为markword和类型指针

    markword存对象运行时数据,比如hashcode,GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳。难怪在看垃圾回收的时候,我还在郁闷,对象在内存中不都长一样吗,怎么还能分得出来呀

    http://blog.csdn.net/u011277123/article/details/53259110

    2.Instance Data实例数据

    对象真正存的有效信息

    3.padding对齐填充

    根据JVM的设计,可以有也可以没有,让整个对象整齐(以8个字节的整数倍形式存在)

    java对象的垃圾回收

    1.新生代

    新生代的对象在每次回收时都会有大量的对象死去,很少一部分存活,选择标记----复制算法

    2.老年代

    标记----清除或者标记----整理

    3.永久代

    转载请注明原文地址: https://ju.6miu.com/read-21650.html

    最新回复(0)