码迷,mamicode.com
首页 > 其他好文 > 详细

【原创】JVM系列04 | 栈上分配

时间:2020-11-24 12:53:51      阅读:7      评论:0      收藏:0      [点我收藏+]

标签:mysql性能优化   对象销毁   是什么   总结   png   cat   汇总   runaway   方法   

【原创】JVM系列04 | 栈上分配
收录于话题
#进阶架构师 | JVM调优专题
9个

点击上方“java进阶架构师”,选择右上角“置顶公众号”
20大进阶架构专题每日送达
技术图片
技术图片
本文是何适 JVM 修仙系列第 4 篇,文末有本系列文章汇总。
当面试官问你对象都分配哪里,你把 JVM 内存结构介绍一下然后说分配在堆上,没啥问题,给你打 8 分。如果你还能聊一聊栈上分配,一定是加分项,我想面试官会考虑给你 10 分。

1. 栈上分配理论


是什么
将线程私有的不可能被其他线程访问的对象打散分配在栈上,而不是分配在堆上。打散分配意思是将对象的不同属性分别分配给不同的局部变量。
好处
栈上分配速度快。
对象销毁不需要垃圾回收,因为方法执行结束后局部变量就销毁了。
缺点
栈空间较小,大对象不适合在栈上分配。

2. 逃逸分析


如何判断对象是线程私有的呢,就要通过逃逸分析。逃逸指的是逃出当前线程,所以逃逸对象就是可以被其他线程访问的对象,非逃逸对象就是线程私有的对象。
举例:逃逸对象和非逃逸对象


public class StackTest {
    public static User user1;

    public static void runAway1() {
        user1 = new User();// 逃逸对象
    }

    public static void runAway2() {
        User user2 = new User();// 非逃逸对象
    }
}

3. 栈上分配举例


举例:非逃逸对象栈上分配

public class StackTest {
    public static User user1;

    public static void runAway1() {
        user1 = new User();// 逃逸对象
        user1.id = 1;
        user1.name = "user";
    }

    public static void runAway2() {
        User user2 = new User();// 非逃逸对象
        user2.id = 2;
        user2.name = "user";
    }

    public static void main(String[] args) {
        for (int i = 0; i <= 99999999; i++) {
            // runAway1();
            runAway2();
        }
    }
}

class User {
    int id;
    String name;
}

执行代码时设置如下参数:

-server -Xss128K -Xmx100m -Xms100m -XX:+PrintGC

-server:server模式下才能设置栈上分配
-Xss128K:栈最大内存
-Xmx100m:堆最大内存
-XX:+PrintGC:打印GC日志

代码中创建一个 User 对象需要 16 字节内存,循环 1 亿次,大概需要 1.5GB 空间。
循环执行runAway1();1 亿次,堆内存 100M 小于 1.5G,所以会发生 GC,打印很多 GC 日志。

[GC (Allocation Failure)  25600K->800K(98304K), 0.0009909 secs]
[GC (Allocation Failure)  26400K->832K(98304K), 0.0006649 secs]
[GC (Allocation Failure)  26432K->776K(98304K), 0.0006009 secs]
[GC (Allocation Failure)  26376K->816K(98304K), 0.0009932 secs]
[GC (Allocation Failure)  26416K->696K(98304K), 0.0009381 secs]
...

循环执行runAway2();1 亿次,由于对象 user2 是线程私有的逃逸对象,执行一次 runAway2()创建一个 User 对象,一次 runAway2()执行完随着局部变量销毁,user2 对象也就销毁了,所以下次执行 runAway2()再创建 user2 对象时还有原来大小的栈空间。循环执行,不会有内存不够的问题,当然也就不会打印出 GC 日志。

4. 总结


技术图片

参考资料

《深入理解 Java 虚拟机(第 2 版) : JVM 高级特性与最佳实践》
《实战 Java 虚拟机 : JVM 故障诊断与性能优化》

JVM 系列文章汇总


【原创】JVM 系列 01 | 开篇
【原创】JVM 系列 02 | Java 虚拟机结构
【原创】JVM 系列 03 | Java 栈—方法是如何调用的?

之前,给大家发过三份Java面试宝典,这次新增了一份,目前总共是四份面试宝典,相信在跳槽前一个月按照面试宝典准备准备,基本没大问题。
《java面试宝典5.0》(初中级)
《350道Java面试题:整理自100+公司》(中高级)
《资深java面试宝典-视频版》(资深)
《Java[BAT]面试必备》(资深)
分别适用于初中级,中高级,资深级工程师的面试复习。
内容包含java基础、javaweb、mysql性能优化、JVM、锁、百万并发、消息队列,高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper、数据结构、限流熔断降级等等。
技术图片
获取方式:点“在看”,V信关注上述单号并回复 【面试】即可领取,更多精彩陆续奉上。

看到这里,证明有所收获
必须点个在看支持呀,喵

【原创】JVM系列04 | 栈上分配

标签:mysql性能优化   对象销毁   是什么   总结   png   cat   汇总   runaway   方法   

原文地址:https://blog.51cto.com/15009303/2552600

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!