二、JVM 内存模型


一、JVM 整体结构

在这里插入图片描述


  • 方法区:
  1. JDK-1.8 前 永久代 或 持久代。
  2. JDK-1.8 元空间,常量、静态变量、类信息。

  • 线程:
  1. 程序计数器(方法区存放的代码的内存地址,由字节码执行引擎变更)。
  2. 栈帧。
  • 栈帧:
  1. 局部变量表。
  2. 操作数栈(临时值)。
  3. 动态链接(方法内部 引用 方法地址)。
  4. 方法出口。
  1. 本地方法栈。

二、JVM 内存模型

在这里插入图片描述


三、JVM 内存参数

在这里插入图片描述


  • JVM 参数配置:
  1. Spring Boot 程序的 java -jar xx.jar 启动脚本里。
  2. Tomcat 直接加在 bin目录 下 catalina.sh 脚本里。
java ‐jar qs‐server.jar \
	# 最小堆。
	‐Xms2048M \
	# 最大堆。
	‐Xmx2048M \
	# 新生代(8:1:1)
	‐Xmn1024M \
	# 栈大小(线程,默认`1M`)。
	‐Xss512K \ 
	# 元空间(方法区)。
	‐XX:MetaspaceSize=256M \
	# 最大元空间。
	‐XX:MaxMetaspaceSize=256M 

1. 栈溢出

/**
 * @author wy
 * describe 栈溢出2。
 * `-Xss128k`配置栈空间(默认`1M`)。
 * <p>
 * 结论:`-Xss`设置越小`count`值就越小。
 * 说明:一个线程栈里能分配的栈帧就越少,但是对`JVM`整体来说能开启的线程数会更多。
 */
public class StackOverflowErrorTest2 {

    private static int count = 0;

    @SuppressWarnings("all")
    private static void redo() {
        count++;
        redo();
    }

    public static void main(String[] args) {
        try {
            redo();
        } catch (Throwable t) {
            t.printStackTrace();
            System.out.println(count);
        }
        /*
        `-Xss128k`,count = 1202
        `-Xss256k`,count = 4217
         */
    }
}

2. 日均百万级订单,JVM 参数配置

在这里插入图片描述


四、逃逸分析


1. JVM 三种运行模式

  1. 解释模式(Interpreted Mode):
    执行一行 JVM 字节码,就编译一行为 机器码。
    只使用解释器(-Xint 强制 JVM 使用 解释模式)。
  2. 编译模式(Compiled Mode):
    先将所有 JVM 字节码 依次编译为 机器码,然后一次性执行所有 机器码。
    只使用编译器(-Xcomp 强制 JVM 使用 编译模式)。
  3. 混合模式(Mixed Mode):
    依然一开始使用 解释模式 执行代码。
    但是对于一些 热点代码 会采用 编译模式 执行。
    编译的 热点代码 对应的 机器码 会被缓存起来,下次再执行无需再编译。
  • JVM 默认采用 混合模式 执行代码

  • 解释模式 启动快
    对于只需要执行 部分代码,并且 大多数代码 只会 执行一次 的情况比较适合。
  • 编译模式 启动慢,但后期执行速度快,而且比较占用内存
    因为 机器码 的数量至少是 JVM字节码 的十倍以上,这种模式适合代码可能会被 反复执行 的场景。
  • 混合模式 默认方式
    这就是常见的 即时编译技术(JIT:Just In Time Compiler)
    即时编译 过程中,JVM 可能会对我们的代码做一些优化(比如:对象逃逸分析 等)。

2. 对象逃逸分析

  • 对象逃逸分析:就是 分析对象动态作用域
    当一个对象在方法中被定义后,它可能被外部方法所引用。
    例如:作为 调用参数 传递到其他地方。
/**
 * @author wy
 * describe 四、逃逸分析。
 * 逃逸分析,来优化对象内存分配位置。
 * `-XX:+DoEscapeAnalysis`开启逃逸分析(`JDK-7`之后默认开启)。
 * `-XX:-DoEscapeAnalysis`关闭逃逸分析。
 */
public class DoEscapeAnalysisTest {

    /**
     * `test`方法中的`person`对象被返回了,这个对象的作用域范围不确定。
     */
    public Person test() {
        Person person = new Person();
        person.setName("wy");
        person.setAge(18);
        return person;
    }

    /**
     * `test2`方法中的`person`对象,可以确定当方法结束,这个对象就可以认为是无效对象了。
     * 对于这样的对象其实可以将其分配到"栈内存"里,让其在方法结束时跟随栈内存一起被回收掉。
     */
    public void test2() {
        Person person = new Person();
        person.setName("qs");
        person.setAge(6);
        System.out.println(person);
    }
}

五、JVM 指令手册


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑士梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值