JVM05_堆的概述、内存结构、复制算法、Minor|Major|Full GC、私有区域TLAB、对象分配、参数总结、逃逸分析、栈上分配、锁消除、标量替换(三)

简介: ⑨. 堆空间参数总结⑩. 逃逸分析

⑨. 堆空间参数总结


①. -XX:+PrintFlagsInitial : 查看所有的参数的默认初始值


②. -XX:+PrintFlagsFinal : 查看所有的参数的最终值(可能会存在修改(:表示修改了),不再是初始值)


③. 具体查看某个参数的指令:


(jps:查看当前运行中的进程


jinfo -flag SurvivorRatio 进程id)


④. -Xms:初始堆空间内存 (默认为物理内存的1/64)


⑤. -Xmx:最大堆空间内存(默认为物理内存的1/4)


⑥. -Xmn:设置新生代的大小。(初始值及最大值)


⑦. -XX:NewRatio:配置新生代与老年代在堆结构的占比


(默认:-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆的1/3


可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整个堆的1/5)


微信图片_20220106140744.png


⑧. -XX:SurvivorRatio:设置新生代中Eden和S0/S1空间的比例


(Eden空间和另外两个Survivor空间缺省所占的比例是8:1:1)


⑨. -XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄


⑩. -XX:+PrintGCDetails:输出详细的GC处理日志


(如下这两种方式是简单的打印


打印gc简要信息:① -XX:+PrintGC ② -verbose:gc)


⑩①. -XX:HandlePromotionFailure:是否设置空间分配担保


(JDK6之后,只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进

行Minor GC,否则将进行Full GC)


内存分配策略(或对象提升(Promotion)规则)


(1). 在繁盛Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间


====如果大于,则此次Minor GC是安全的


====如果小于,则虚拟机会检查查看-XX:HandlePromotionFailure设置值是否允许担保失败


=====如果 HandlePromotionFailure=true,那么会继续检查老年代最大可用连续空间是否大于历次晋级到老年代的对象的平均大小


========如果大于,则尝试进行一次Minor GC,但是这次Minor GC依然是有风险的


========如果小于,则改为一次Full GC


=====如果HandlePromotionFailure=false,则改为进行一次Full GC


(2). 在JDK6 Update24之后,HandlePromotionFailure参数不会再影响虚拟机的空间分配担保策略,观察OpenJDK中源码变化,虽然源码中还定义了HandlePromotionFailure参数,但是在代码中已经不会再使用它


(3). JDK6 Update24之后规则变为只有老年代的连续空间大于新生代对象总大小或者历次晋身的平均大小就会进行Minor GC,否则将进行Full GC


⑩. 逃逸分析


  • ①. 如何将堆上的对象分配到栈,需要使用逃逸分析手段


  1. 当一个对象在方法中被定义后,对象只在方法内部使用(这里关注的是这个对象的实体),则认为没有发生逃逸。


  1. 当一个对象在方法中被定义后,它被外部方法所引用,则认为发生逃逸。例如作为调用参数传递到其他地方中


  • ②. 代码演示


//(1). 没有发生逃逸的对象,则可以分配到栈上,随着方法执行的结束,栈空间就被移除
public void my_method() {
    V v = new V();
    // use v
    // ....
    v = null;
}
//(2). 下面代码中的 StringBuffer sb 发生了逃逸
public static StringBuffer createStringBuffer(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb;
}
//如果想要StringBuffer sb不发生逃逸,可以这样写
public static String createStringBuffer(String s1, String s2) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    return sb.toString();
}

③. 逃逸分析的举例


/**
 * 逃逸分析
 *
 * 如何快速的判断是否发生了逃逸分析,大家就看new的对象实体是否有可能在方法外被调用。
 */
public class EscapeAnalysis {
    public EscapeAnalysis obj;
    /*
    方法返回EscapeAnalysis对象,发生逃逸
     */
    public EscapeAnalysis getInstance(){
        return obj == null? new EscapeAnalysis() : obj;
    }
    /*
    为成员属性赋值,发生逃逸
     */
    public void setObj(){
        this.obj = new EscapeAnalysis();
    }
    //思考:如果当前的obj引用声明为static的? 仍然会发生逃逸。
    /*
    对象的作用域仅在当前方法中有效,没有发生逃逸
     */
    public void useEscapeAnalysis(){
        EscapeAnalysis e = new EscapeAnalysis();
    }
    /*
    引用成员变量的值,发生逃逸
     */
    public void useEscapeAnalysis1(){
        EscapeAnalysis e = getInstance(); //这个e对象,本身就是从外面的方法逃逸进来的
        //getInstance().xxx()同样会发生逃逸
    }
}


④. 在JDK1.7版本之后,HotSpot中默认就已经开启了逃逸分析


如果使用的是较早的版本,开发人员则可以通过:


选项“-XX:+DoEscapeAnalysis"显式开启逃逸分析


通过选项“-XX:+PrintEscapeAnalysis"查看逃逸分析的筛选结果


  • 结论: ⑤. 开发中能使用局部变量的,就不要使用在方法外定义


  • ⑥. 使用逃逸分析,编译器可以对代码做如下优化:


栈上分配:将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会发生逃逸,对象可能是栈上分配的候选,而不是堆上分配


同步省略:如果一个对象被发现只有一个线程被访问到,那么对于这个对象的操作可以不考虑同步。


分离对象或标量替换:有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中


相关文章
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
38 4
|
23天前
|
算法
虚拟内存的页面置换算法有哪些?
【10月更文挑战第25天】不同的页面置换算法各有优缺点,在实际应用中,操作系统会根据不同的应用场景和系统需求选择合适的页面置换算法,或者对算法进行适当的改进和优化,以平衡系统的性能、开销和资源利用率等因素。
44 5
|
2月前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
2月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
51 3
|
2月前
|
Java Android开发 开发者
【编程进阶知识】精细调控:掌握Eclipse JVM参数配置的艺术
本文详细介绍了如何在Eclipse中配置JVM参数,包括内存的初始和最大值设置。通过具体步骤和截图演示,帮助开发者掌握JVM参数的精细调控,以适应不同的开发和测试需求。
45 1
|
2月前
|
存储 安全 Java
JVM锁的膨胀过程与锁内存变化解析
在Java虚拟机(JVM)中,锁机制是确保多线程环境下数据一致性和线程安全的重要手段。随着线程对共享资源的竞争程度不同,JVM中的锁会经历从低级到高级的膨胀过程,以适应不同的并发场景。本文将深入探讨JVM锁的膨胀过程,以及锁在内存中的变化。
44 1
|
2月前
|
存储 Kubernetes 架构师
阿里面试:JVM 锁内存 是怎么变化的? JVM 锁的膨胀过程 ?
尼恩,一位经验丰富的40岁老架构师,通过其读者交流群分享了一系列关于JVM锁的深度解析,包括偏向锁、轻量级锁、自旋锁和重量级锁的概念、内存结构变化及锁膨胀流程。这些内容不仅帮助群内的小伙伴们顺利通过了多家一线互联网企业的面试,还整理成了《尼恩Java面试宝典》等技术资料,助力更多开发者提升技术水平,实现职业逆袭。尼恩强调,掌握这些核心知识点不仅能提高面试成功率,还能在实际工作中更好地应对高并发场景下的性能优化问题。
|
2月前
|
存储 算法 C语言
MacOS环境-手写操作系统-17-内存管理算法实现
MacOS环境-手写操作系统-17-内存管理算法实现
37 0
|
4月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
332 0
|
2月前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。