jvm底层运行原理(中)

1. java内存模型(JMM)
说JMM之前,先说说三大特性,原子性,可见性,有序性。
原子性:一个操作要么成功,要么失败,不会被中断。比如java中的赋值语句 int i=1就是原子性的;
int j = i就不是原子性的,程序包含了两个操作,从主内存读取i的值,将j的值存入工作内存。
可见性:一个线程操作了变量,对另外的线程是可见的,下面的volatile关键字就是保证变量可见性的。
有序性:在Java内存模型中,允许编译器和处理器对指令进行重排序,在单线程中不影响程序结果,多线程就会影响。java先天就保证了程序在一定程度的有序(happen-before原则).
在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的;java线程模型定义了程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取出变量这样的底层细节。
具体的规则就是:所有的变量都存在主内存,主内存是每个线程共享的,每个线程都有自己的工作内存,存的是所用到的变量副本,线程不能直接去操作主内存中的变量,而是操作自己的工作内存,然后同步到主内存;线程之间通过主内存通信。在这里插入图片描述
2. Volatile关键字
volatile关键字主要就是保证变量在多线程间的可见性(不保证原子性),一个被volatile修改的变量,如果一个线程修改了这个变量的值后会被强制要求将值立即写入主存,并且会使其他线程的工作内存中这个变量的副本失效,其他线程再读取此变量时就会从主内存中读取。
禁止指令重排序:被volatile修改的变量在编译成汇编时会多出一个lock前缀指令,相当于内存屏障,保证执行到这时前面的代码已经执行完了。
3.JVM实用参数
-XX:+PrintGCDetails(打印GC日志信息);可以在本地测试在这里加上这个参数看控制台:在这里插入图片描述
可以看到打印的一下堆信息。
-XX:+TraceClassLoading(类加载信息)
-Xloggc:d:/gc.log (日志目录)
-Xmx(最大堆)
-Xms(最小队堆值)
-Xss(栈大小)
-Xmn(新生代大小eden+2s),默认比例是8:1:1,jdk1.8 survivor区最小是512k
–XX:NewRatio(年轻代(eden+2s):老年代)
–XX:SurvivorRatio(2s:eden )
4.JVM内存垃圾收集算法
标记-清除算法:分为两个阶段,标记阶段(引用计数和不可达)和清楚阶段,标记存活的对象,统一清除所有未标记的对象。(缺点:产生内存碎片,效率不高)
复制算法:内存一分为二,每次只使用其中一块,当一块内存没有连续空间存储对象的时候,会把存活下来的对象复制到另外一块内存中,然后一次性清除之前的哪块空间(缺点:内存变小了)
标记-整理算法:将所有的存活对象压缩到内存的一端,然后清理边界外所有的空间,适合用于存活对象较多的场合,如老年代
分代收集算法: 分代思想,堆划分为新生代和老年代; 新生代中,能够存活的对象很少,可以使用复制算法;老年代中,对象存活率高,而且没有额外的空间用来做老年代的担保,可以使用标记清除或者标记整理算法(新生代中eden区和survivor默认比例是8:1)。
5.垃圾收集器

  • Serial 新生代串行收集器 新(复制算法,适用于运行在client模式下的虚拟机),老(标记整理)
  • ParNew 新生代并行收集器
  • Parallel Scavenge 新生代并行收集器(复制算法,jdk1.8默认)在注重吞吐量或CPU资源敏感的场合,可以优先考虑Parallel Scavenge收集器 + Parallel Old收集器。
  • Serial Old 老年代串行收集器
  • Parallel Old 老年代并行收集器
  • CMS 真正意义上的并发收集器(老年代收集器,采用“标记-清除”),目标:最短的GC停顿时间,分为四个阶段,初始标记 并发标记 重新标记 并发清除,缺点(并发时占用cpu资源,会产生浮动垃圾,产生大量空间碎片,有gc阀值,jdk1.5->68%)
  • G1(并发执行,不会产生空间碎片,可预测的GC停顿-》划分多个region,用remembered Set存跨区域的应用,避免全堆扫描;优化回收价值最大的region;初始标记-并发标记-最终标记-筛选回收)

在这里插入图片描述
对象生存:对象开始分配在eden区,经过一次minor gc后,如果还能存活,并且surrvivor能装下这个对象,就会移到surrvivor区,默认在survivor区gc年龄达到15次就进入老年代,如果surrvovor不能装下就通过担保进入老年代。如果在survivor空间中相同年龄所有对象的大小总和大于survivor空间的一半,年龄等于或者大于该对象就可以直接进入老年代。(-XX: MaxTenuringThreshold=15,设置对象最大年龄代才进入老年代)

参考资料:《深入理解java虚拟机》

发布了42 篇原创文章 · 获赞 29 · 访问量 2554

猜你喜欢

转载自blog.csdn.net/qq_32314335/article/details/85499300