jvm 相关知识点

1、jvm的组成

类加载器- 内存- 执行引擎- 本地方法调用

如下图

 

 1、类加载器

.java 文件-编译.class 文件 类加载器就是主要加载.class 文件的。双亲委派机制

详解

https://blog.csdn.net/dam454450872/article/details/103502328

2、执行引擎 

执行字节码,或者执行本地方法

3、本地方法调用,

就是本地方法(用native)修饰的,直接访问本地方法栈

4、内存

内存由,堆、 栈、本地方法栈、方法区、程序寄存器(控制指令走到哪一行了)

堆和方法区市线程共享的,其他的是线程私有的

如该方法为native的,则PC寄存器中不存储任何信息。

怎么判断一个对象是否能被 回收

两种方法:

1、引用计数法,就是判断这个 对象的引用有几次,引用一次加一,引用失效就减一,如果为了0 了就可以回收了

2、可达性分析、

通过一系列称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(即对象到GC Roots不可达),则证明此对象已死、可回收。Java中可以作为GC Roots的对象包括:虚拟机栈中引用的对象、本地方法栈中Native方法引用的对象、方法区静态属性引用的对象、方法区常量引用的对象。

https://blog.csdn.net/yunzhaji3762/article/details/81038711

垃圾回收算法

1、标记清除算法

对那些没有标记的对象进行清除,缺点就是效率低,会有内存碎片,导致空间不连续

2、标记整理算法

如上把标记,清除的对象都移到边缘就不会有空间不连续了,解决了内存碎片的问题

3、复制算法

就是复制两个空间

4、分代回收算法

新生代和老年代,方法区称为永久代(在新的版本中已经将永久代废弃,引入了元空间的概念,永久代使用的是JVM内存而元空间直接使用物理内存

新生代中的对象“朝生夕死”,每次GC时都会有大量对象死去,少量存活,使用复制算法。新生代又分为Eden区和Survivor区(Survivor from、Survivor to),大小比例默认为8:1:1。

老年代中的对象因为对象存活率高、没有额外空间进行分配担保,就使用标记-清除或标记-整理算法。

新产生的对象优先进去Eden区,当Eden区满了之后再使用Survivor from,当Survivor from 也满了之后就进行Minor GC(新生代GC),将Eden和Survivor from中存活的对象copy进入Survivor to,然后清空Eden和Survivor from,这个时候原来的Survivor from成了新的Survivor to,原来的Survivor to成了新的Survivor from。复制的时候,如果Survivor to 无法容纳全部存活的对象,则根据老年代的分配担保(类似于银行的贷款担保)将对象copy进去老年代,如果老年代也无法容纳,则进行Full GC(老年代GC)。

大对象直接进入老年代:JVM中有个参数配置-XX:PretenureSizeThreshold,令大于这个设置值的对象直接进入老年代,目的是为了避免在Eden和Survivor区之间发生大量的内存复制。

长期存活的对象进入老年代:JVM给每个对象定义一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳,将被移入Survivor并且年龄设定为1。没熬过一次Minor GC,年龄就加1,当他的年龄到一定程度(默认为15岁,可以通过XX:MaxTenuringThreshold来设定),就会移入老年代。但是JVM并不是永远要求年龄必须达到最大年龄才会晋升老年代,如果Survivor 空间中相同年龄(如年龄为x)所有对象大小的总和大于Survivor的一半,年龄大于等于x的所有对象直接进入老年代,无需等到最大年龄要求。

 

posted @ 2020-03-26 11:30  potent_prince  阅读(115)  评论(0编辑  收藏  举报