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寄存器中


相关文章
|
7月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
675 55
|
8月前
|
存储 NoSQL Redis
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 +  无锁架构 +  EDA架构  + 异步日志 + 集群架构
|
9月前
|
SQL 存储 缓存
【赵渝强老师】达梦数据库的内存结构
本文介绍了达梦数据库管理系统的内存结构,包括内存池、缓冲区、排序区和哈希区。内存池分为共享内存池和运行时内存池,能够提高内存申请与释放效率,并便于监控内存使用情况。缓冲区涵盖数据缓冲区、日志缓冲区、字典缓冲区和SQL缓冲区,用于优化数据读写和查询性能。排序区和哈希区分别提供排序和哈希连接所需的内存空间,通过合理配置参数可提升系统效率。文内附有具体配置示例及视频讲解,帮助用户深入理解达梦数据库的内存管理机制。
279 0
|
12月前
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
164 3
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
2月前
|
存储 缓存 Java
我们来说一说 JVM 的内存模型
我是小假 期待与你的下一次相遇 ~
237 5
|
2月前
|
存储 缓存 算法
深入理解JVM《JVM内存区域详解 - 世界的基石》
Java代码从编译到执行需经javac编译为.class字节码,再由JVM加载运行。JVM内存分为线程私有(程序计数器、虚拟机栈、本地方法栈)和线程共享(堆、方法区)区域,其中堆是GC主战场,方法区在JDK 8+演变为使用本地内存的元空间,直接内存则用于提升NIO性能,但可能引发OOM。
|
8月前
|
Arthas 监控 Java
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
662 6
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
2066 1

热门文章

最新文章