迟来的jvm学习
这章可能要掺点水 就算是补充了
提前打个广告 推荐孙千的一部电视剧 在这个时代这样淳朴的爱情不多

探讨finally的面试问题
书接上次 继续关于参数的分析
public class Mian_finally {public static void main(String[] args) {int a = result();System.out.println(a);}public static int result() {try {
// int i=1/0;return 10;} finally {return 20;}}
}
然后编译分析参数
0: bipush 10 10压入栈顶2: istore_0 移除栈顶3: bipush 20 20压入栈顶5: ireturn 返回栈顶6: astore_1 0-3出现异常到这里7: bipush 20 20压入栈顶9: ireturn 返回Exception table:from to target type0 3 6 any
如果我们加入int i=1/0
按照常理我们觉得会报错 但是执行结果任然是20
因为finally中出现的return语句会将异常吞掉
上述0-3 any任何异常都会跳到6执行 return 20语句
再看一道finally题目
public class Mian_finally2 {public static void main(String[] args) {int a = result();System.out.println(a);}public static int result() {int i = 10;try {return i;} finally {i = 20;}}
}
关于结果不难理解返回10 输出结果a就是10 i最终变成了20
实际上i没了 我们看一下参数分析就行
finally的修改值不会影响那个槽位的值
局部变量中的i值最终修改为20 但返回值10已经锁定拿走了 方法结束后20就回收了
语法糖
实际上就是.java源码编译为.class字节码的过程中 自动生成和转换的一些代码
idea中已经集成了工具FernFlower
我们做几个验证
使用CFR或FernFlower对.class文件消化语法糖
使用idea自带FernFlower翻译
例如这段代码
public class Test_Candy {public static void main(String[] args) {int[] list = {1, 2, 3};for (int i : list) {System.out.println(i);}}
}
可以看到关于语法糖的转换
CFR翻译
例如:
自动拆装箱
public class Candy_Box {public static void main(String[] args) {Integer a=3;int b=a;}
}
先需要下一个cfr
https://www.benf.org/other/cfr/
肯定不方便用 只不过做个了解
java -jar cfr-0.152.jar Test_Candy.class
最后再介绍个逃逸分析
运行期优化-逃逸分析 为的就是JVM自动进行优化减少堆分配提高性能
若对象并未出去方法外就是没发生逃逸 JVM就可以优化
这样就不需要再占用堆 直接将对象放在栈里(栈上分配)
将对象拆成更小的数据标量(标量替换)
妈的简单点理解就是 只要这个创建的对象不逃出去方法 jvm就可以就行逃逸分析 不用干到堆上减少消耗提高性能
来一个gpt给的案例看看
public class Test_escapes {public static void main(String[] args) {long start = System.currentTimeMillis();for(int i=0;i<10000000;i++){alloc();}System.out.println(System.currentTimeMillis()-start);}private static void alloc(){User user = new User();}static class User{int age;}
}
运行消耗时间

默认是启用了逃逸分析的
加入参数关闭 -XX:-DoEscapeAnalysis 关闭逃逸分析

运行后

?????????
关了逃逸分析为何时间消耗还少了 我理解错了? 当然不是 接着往下看
看代码 我们前面提到标量替换 对象啥都没干 直接就给你弄成标量了
修改代码 让创建的对象必须干事
public class Test_escapes {public static void main(String[] args) {long sum = 0;long start = System.currentTimeMillis();for(int i=0;i<100000000;i++){sum += alloc();}System.out.println(sum);System.out.println(System.currentTimeMillis()-start);}private static int alloc(){User user = new User();user.age = 18;return user.age;}static class User{int age;}
}
关闭前后










