01 | Java代码是怎么运行的?
01 | Java代码是怎么运行的?
讲述:郑雨迪
时长10:37大小6.09M
为什么 Java 要在虚拟机里运行?
Java 虚拟机具体是怎样运行 Java 字节码的?
Java 虚拟机的运行效率究竟是怎么样的?
总结与实践
赞 58
提建议
精选留言(206)
- jiaobuchongจุ๊บ置顶2018-10-14对老师写的那段 awk 不懂得可参考: https://blog.csdn.net/jiaobuchong/article/details/83037467共 1 条评论96
- 小名叫大明置顶2018-07-26受益匪浅,多谢老师。 请教老师一个问题,网上我没有搜到。 服务器线程数爆满,使用jstack打印线程堆栈信息,想知道是哪类线程数太多,但是堆栈里全是一样的信息且没有任何关键信息,是哪个方法创建的,以及哪个线程池的都看不到。 如何更改打印线程堆栈信息的代码(动态)让其打印线程池信息呢?展开共 4 条评论48
- 曲东方2018-07-20jvm把boolean当做int来处理 flag = iconst_1 = true awk把stackframe中的flag改为iconst_2 if(flag)比较时ifeq指令做是否为零判断,常数2仍为true,打印输出 if(true == flag)比较时if_cmpne做整数比较,iconst_1是否等于flag,比较失败,不再打印输出展开
作者回复: 字节码高手!
共 10 条评论419 - novembersky2018-07-20文中提到虚拟机会把部分热点代码编译成机器码,我有个疑问,为什么不把java代码全部编译成机器码?很多服务端应用发布频率不会太频繁,但是对运行时的性能和吞吐量要求较高。如果发布或启动时多花点时间编译,能够带来运行时的持久性能收益,不是很合适么?
作者回复: 问得好!事实上JVM确实有考虑做AOT (ahead of time compilation) 这种事情。AOT能够在线下将Java字节码编译成机器码,主要是用来解决启动性能不好的问题。 对于这种发布频率不频繁(也就是长时间运行吧?)的程序,其实选择线下编译和即时编译都一样,因为至多一两个小时后该即时编译的都已经编译完成了。另外,即时编译器因为有程序的运行时信息,优化效果更好,也就是说峰值性能更好。
共 7 条评论144 - 醉人2018-07-20解释执行 执行时才翻译成机器指令,无需保存不占内存。但即时编译类似预编译,编译之后的指令需要保存在内存中,这种方式吃内存,按照二八原则这种混合模式最恰当的,热点代码编译之后放入内存避免重复编译,而其他运行次数较少代码则解释执行,避免占用过多内存共 1 条评论130
- かっこいすぎる郑一凡2018-07-20我想问下,JVM是怎么区别出热点代码和非热点代码的?共 12 条评论101
- MARK2018-07-25作业终于做出来~\(≧▽≦)/~喜大普奔 asmtools下载地址: https://adopt-openjdk.ci.cloudbees.com/view/OpenJDK/job/asmtools/lastSuccessfulBuild/artifact/asmtools-6.0.tar.gz; 先是在window环境里,awk不能使用,看https://zh.wikipedia.org/wiki/Awk,AWK是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一,于是转战Linux, [root@localhost cqq]# javac Foo.java [root@localhost cqq]# java Foo Hello,Java Hello,JVM [root@localhost cqq]# java -cp /cqq/asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class>Foo.jasm.1 [root@localhost cqq]# ls asmtools.jar Foo.class Foo.jasm.1 Foo.java [root@localhost cqq]# vi Foo.jasm.1 [root@localhost cqq]# awk 'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_2")} 1' Foo.jasm.1>Foo.jasm [root@localhost cqq]# java -cp /cqq/asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm [root@localhost cqq]# java Foo Hello,Java 结果为啥是这个看点赞第一的高手; 另外asmtools使用方式还可以这样子: java -jar asmtools.jar jdis Foo.class>Foo.jasm.1 java -jar asmtools.jar jasm Foo.jasm展开共 5 条评论94
- 之外^Excepts2018-07-21我只想问,你就没有教授的担忧?万一我拿今天的知识点去问面试者,答不上来咋办?66
- 钱2018-07-241:为什么使用JVM? 1-1:可以轻松实现Java代码的跨平台执行 1-2:JVM提供了一个托管平台,提供内存管理、垃圾回收、编译时动态校验等功能 1-3:使用JVM能够让我们的编程工作更轻松、高效节省公司成本,提示社会化的整体快发效率,我们只关注和业务相关的程序逻辑的编写,其他业务无关但对于编程同样重要的事情交给JVM来处理 2:听完此节的课程的疑惑(之前就没太明白,原期待听完后不再疑惑的) 2-1:Java源代码怎么就经过编译变成了Java字节码? 2-2:JVM怎么就把Java字节码加载进JVM内了?先加载那个类的字节码?它怎么定位的?拿到后怎么解析的?不会整个文件放到一个地方吧?使用的时候又是怎么找到的呢?这些感觉还是黑盒 2-3:JVM将内存区域分成堆和栈,然后又将栈分成pc寄存器、本地方法栈、Java方法栈,有些内存空间是线程可共享的,有些是线程私有的。现在也了解不同的内存区块有不同的用处,不过他们是怎么被划分的哪?为什么是他们,不能再多几种或少几种了吗?共享的内存区和私有的又是怎么控制的哪?展开
作者回复: 总结得非常细致! 2-1 其实是这样的,JVM接收字节码,要运行在JVM上只能选择转化为字节码。要是不想在JVM上跑,可以选择直接转化为机器码。 2-2 类加载会在第三篇详细介绍。 2-3 具体的划分都是实现细节。你也可以选择全部冗杂在一起。但是这样子做性能较高,因为线程私有的可以不用同步。
53 - J2018-12-25在Windows使用不了awk工具(貌似有代替方案),所以结合其他小伙伴的答案和自己的思考,答案整理如下: 小作业的过程是: 1、写Java代码,生成java文件 2、将java文件编译成class文件(字节码) 3、执行字节码,输出两个Hello,world! 4、使用asmtool工具将class文件生成jasm文件 5、使用awt工具将jasm文件stackframe的flag改为iconst_2 6、再次使用asmtool工具将jasm文件恢复成class文件 7、执行字节码,输出一个Hello, world! 由于Java虚拟机将boolean类型看成0或者1,在步骤5中将源代码中的flag修改成2,于是在步骤7中的运行过程中,if(2),true,执行输出;if(2 == 1),结果为false,不执行输出。展开共 3 条评论49
- Ryan-Hou2018-07-20在为什么Java要在虚拟机里执行这一节您提到,java语法复杂,抽象度高,直接通过硬件来执行不现实,但是同样作为高级语言为什么C++就可以呢?这个理由作为引入虚拟机这个中间层的原因不是很充分吧
作者回复: 多谢指出!这里的直接运行指的是不经过任何转换(编译),直接在硬件上跑。即便是C++,也不可以直接运行。 C++的策略是直接编译成目标架构的机器码,Java的策略是编译成一个虚拟架构的机器码。这个虚拟架构可以有物理实现(可以搜Java processor),也可以是软件实现,也就是我们经常接触到的JRE。
共 2 条评论41 - 周仕林2018-07-23看到有人说热点代码的区别,在git里面涉及到的热点代码有两种算法,基于采样的热点探测和基于计数器的热点探测。一般采用的都是基于计数器的热点探测,两者的优缺点百度一下就知道了。基于计数器的热点探测又有两个计数器,方法调用计数器,回边计数器,他们在C1和C2又有不同的阈值。😂😂
作者回复: 谢谢!
共 2 条评论36 - kernel2018-08-13评论比文章精彩,学习到更多26
- 尔东2018-12-301.Java代码首先编译为class文件,然后通过java虚拟机加载到方法区。Java虚拟机是一个独立的进程,执行方法区的代码。 2.Java虚拟机把内存分为堆栈两种形式来存储运行时数据,包括线程共有的方法区和堆,以及线程私有的pc计数器,方法栈,naive方法栈 3.Java虚拟机将字节码翻译成机器码执行的方法有两种,一种是解释执行,即逐条将字节码翻译成机器码并执行;第二种是即时编译,即将一个方法包含的所有字节码编译成机器码后再执行 4.解释执行的好处是无需等待编译,即时编译的好处是速度更快。这里编译的概念并不是代码编译为字节码,而是字节码编译为机器码,字节码编译为机器码是由java虚拟机在运行程序的时候才会去做的,所以是运行时的开销。热点代码会通过即时编译来执行。 5.HotSpot内置了多个即时编译器,包括C1、C2和Graal。 6.Asmtools.jar下载地址https://ci.adoptopenjdk.net/view/Dependencies/job/asmtools/lastSuccessfulBuild/ 7.JVM将Boolean类型看作是int类型,true就是1,false就是0,flag如果改成2第二个判1等式就不成立,所以只有第一个判0等式通过。展开共 6 条评论22
- mj4ever2018-10-05Java语言规范中,boolean类型的只有两种 true和false(false是默认值); Java虚拟机规范中,boolean类型要转换为int类型,true => 1,false => 0; 在编译而成的class文件中,除了字段和传入参数外,基本看不出boolean类型: 比如,第一次时为: public class Foo { public Foo() { } public static void main(String[] var0) { byte flag = 1; if (flag != 0) { System.out.println("Hello, Java!"); } if (flag == 1) { System.out.println("Hello, JVM!"); } } } 第2次执行时,正则表达式将flag替换为2: public class Foo { public Foo() { } public static void main(String[] var0) { byte flag = 2; if (flag != 0) { System.out.println("Hello, Java!"); } if (flag == 1) { System.out.println("Hello, JVM!"); } } }展开共 3 条评论22
- 笨笨蛋2018-07-24什么时候使用C1,什么时候使用C2,他是怎么区分热点方法的呢?
作者回复: 刚刚看到一个同学总结了。JVM会统计每个方法被调用了多少次,超过多少次,那就是热点方法。(还有个循环回边计数器,用来编译热循环的。) 默认的分层编译应该是达到两千调C1,达到一万五调C2。
共 4 条评论19 - ace2018-08-05最后awk那段分析了下。希望分析正确 也对大家有帮助 1、NR==1,/iconst_1/ 是用于匹配行 匹配第一行到第一个出现iconst_1的行 2、{}进行脚本执行。针对第一步中匹配的行执行内置的字符串函数sub 做替换 3、1 都会被执行。在awk 1被计算为true,表现为默认操作 print $0 也就是打印整行 整体效果是打印所以文本行,但第一个出现iconst_1的做替换。17
- 那我懂你意思了2018-07-20老师,那个pc寄存器,本地方法栈,以及方法栈,java方法栈这三个组成的就是我们常统称的栈吧,然后也叫栈帧?
作者回复: JVM里的栈指的应该是Java方法栈和本地方法栈。每个方法调用会在栈上划出一块作为栈帧(stack frame)。栈是由多个栈帧构成的,就好比电影是由一个个帧构成的。
共 3 条评论17 - 踏雪无痕2018-07-20您好,我现在所在的项目经常堆外内存占用非常多,超过总内存的70%,请问一下有没有什么方法能观察一下堆外内存有什么内容?
作者回复: 堆外内存的话,就把JVM当成普通进程来查找内存泄漏。可以看下Google Performance Tools相关资料
15 - 陈树义2018-07-21asmtools.jar 是在哪里下载的,怎么在给的链接页面没找到。共 2 条评论14