diff --git a/README.md b/README.md index ef6dd85ac42b3a30cb8329a1ff08d8880c301aed..a0a0e0d1dc38c2ab46ea28ce46d3ca5bd0917220 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ - [JVM到底是如何运行Java代码的?](docs/jvm/how-run-java-code.md) - [我竟然不再抗拒Java的类加载机制了](docs/jvm/class-load.md) - [详解Java的类文件(class文件)结构](docs/jvm/class-file-jiegou.md) -- [javap的角度轻松看懂字节码](docs/jvm/bytecode.md) +- [从javap的角度轻松看懂字节码](docs/jvm/bytecode.md) - [JVM字节码指令详解](docs/jvm/zijiema-zhiling.md) - [虚拟机是如何执行字节码指令的?](docs/jvm/how-jvm-run-zijiema-zhiling.md) - [HSDB(Hotspot Debugger)从入门到实战](docs/jvm/hsdb.md) diff --git a/docs/jvm/asm.md b/docs/jvm/asm.md index 552ebc4bb2cadd161950601f210f808c96f696c4..a0a17b2a921e0387ae40fb66d6036fba8488a963 100644 --- a/docs/jvm/asm.md +++ b/docs/jvm/asm.md @@ -18,7 +18,7 @@ We are all in the gutter, but some of us are looking at the stars. (我们都 ASM是一种通用Java字节码操作和分析框架。它可以用于修改现有的class文件或动态生成class文件。 -> **ASM **is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify existing classes or to dynamically generate classes, directly in binary form. ASM provides some common bytecode transformations and analysis algorithms from which custom complex transformations and code analysis tools can be built. ASM offers similar functionality as other Java bytecode frameworks, but is focused on[performance](https://link.zhihu.com/?target=https%3A//asm.ow2.io/performance.html). Because it was designed and implemented to be as small and as fast as possible, it is well suited for use in dynamic systems (but can of course be used in a static way too, e.g. in compilers). +> **ASM **is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify existing classes or to dynamically generate classes, directly in binary form. ASM provides some common bytecode transformations and analysis algorithms from which custom complex transformations and code analysis tools can be built. ASM offers similar functionality as other Java bytecode frameworks, but is focused on[performance](https://asm.ow2.io/performance.html). Because it was designed and implemented to be as small and as fast as possible, it is well suited for use in dynamic systems (but can of course be used in a static way too, e.g. in compilers). 本篇文章分享的是对ASM的理解和应用,之前需要我们掌握**class字节码**,**JVM基于栈的设计模式,JVM指令** @@ -26,7 +26,7 @@ ASM是一种通用Java字节码操作和分析框架。它可以用于修改现 我们编写的java文件,会通过javac命令编译为class文件,JVM最终会执行该类型文件来运行程序。下图所示为class文件结构。 -![](https://upload-images.jianshu.io/upload_images/1179389-17f68ac5dabe8d33.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/asm-43844b78-c01f-4990-b038-3c91ff2eeb34.jpg) 下面我们通过一个简单的实例来进行说明。下面是我们编写的一个简单的java文件,只是简单的函数调用. @@ -185,7 +185,7 @@ SourceFile: "Test.java" JVM的指令集是基于栈而不是寄存器,基于栈可以具备很好的跨平台性。在线程中执行一个方法时,我们会创建一个栈帧入栈并执行,如果该方法又调用另一个方法时会再次创建新的栈帧然后入栈,方法返回之际,原栈帧会返回方法的执行结果给之前的栈帧,随后虚拟机将会丢弃此栈帧。 -![](https://upload-images.jianshu.io/upload_images/1179389-9173e9d3cc8fd537.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/asm-e31b7e50-1d48-4eef-9552-6fa7e6c68fed.jpg) ### 局部变量表 @@ -237,9 +237,9 @@ public int sub(int, int); a = b + c 的字节码执行过程中操作数栈以及局部变量表的变化如下图所示 -![](https://upload-images.jianshu.io/upload_images/1179389-c5ccfcca3e6fabaa.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/asm-4670450e-6199-4562-9cf4-354234c734c8.jpg) -![](https://upload-images.jianshu.io/upload_images/1179389-4d970cd306753276.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/asm-9808d639-327f-4796-80d4-1809be0b9106.jpg) ## ASM操作 @@ -340,7 +340,7 @@ mv.visitEnd(); 可以一键生成对应的ASM API代码 -![](https://upload-images.jianshu.io/upload_images/1179389-d9960e4e54e3f547.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/asm-3c8c8db4-5b6a-4576-b147-62965d0e0c1c.jpg) ---- diff --git a/docs/jvm/bytecode.md b/docs/jvm/bytecode.md index b6508bd3c28f4f0eb89f90971f809625ab7427a0..17d19f7df57f45772c0cdaacf3fac87ed2deac54 100644 --- a/docs/jvm/bytecode.md +++ b/docs/jvm/bytecode.md @@ -6,7 +6,7 @@ tag: - Java --- -# 轻松看懂字节码 +# 从javap的角度轻松看懂字节码 ### 01、字节码 @@ -20,7 +20,7 @@ tag: 如今的 Java 虚拟机非常强大,不仅支持 Java 语言,还支持很多其他的编程语言,比如说 Groovy、Scala、Koltin 等等。 -![](https://img-blog.csdnimg.cn/img_convert/c0f46bd591311e119d125e34c2ae4c5a.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-dd31bbd6-c75c-4426-9437-c0f57ea3b86f.png) 来看一段代码吧。 @@ -35,7 +35,7 @@ public class Main { 编译生成 Main.class 文件后,可以在命令行使用 `xxd Main.class` 打开 class 文件(我用的是 Intellij IDEA,在 macOS 环境下)。 -![](https://img-blog.csdnimg.cn/img_convert/249e68ae6e099a96b4c9936e627305a2.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-bd941085-ff0e-4abf-a5f9-afb0493bfed7.png) @@ -51,7 +51,7 @@ public class Main { Java 内置了一个反编译命令 javap,可以通过 `javap -help` 了解 javap 的基本用法。 -![](https://img-blog.csdnimg.cn/img_convert/1ac81d072e7a39e732f7aee755881640.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-84b7af5c-93b1-4f63-bb30-946ab3d7e98c.png) OK,我们输入命令 `javap -v -p Main.class` 来查看一下输出的内容。 @@ -184,7 +184,7 @@ flags: (0x0021) ACC_PUBLIC, ACC_SUPER 类访问标记,一共有 8 种。 -![](https://img-blog.csdnimg.cn/img_convert/f6ad24641d314f5dd1b271aeeb41223d.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-d12d6983-f427-40d2-bb4b-3a2c6c4c7806.png) 表明当前类是 `ACC_PUBLIC | ACC_SUPER`。位运算符 `|` 的意思是如果相对应位是 0,则结果为 0,否则为 1,所以 `0x0001 | 0x0020` 的结果是 `0x0021`(需要转成二进制进行运算)。 @@ -332,7 +332,7 @@ Java 虚拟机是在加载字节码文件的时候才进行的动态链接,也 关于字段类型的描述符映射表如下图所示。 -![](https://img-blog.csdnimg.cn/img_convert/f0833aa50e5df619c4f00bbcc0ae16b4.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-cbf16ce9-7853-4050-a1c0-8b874f3b0c1e.png) 到此为止,第 2 个常量算是摸完了。组合起来的意思就是,声明了一个类型为 int 的字段 age。 @@ -364,7 +364,7 @@ private int age; 字段的访问标志和类的访问标志非常类似。 -![](https://img-blog.csdnimg.cn/img_convert/35d14839a3f4de81fbb676b035537435.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-5f328e11-3486-4eb4-8fa9-5c5febfab894.png) @@ -373,7 +373,7 @@ private int age; 方法表用来描述接口或者类中声明的方法,包括类方法和成员方法,以及构造方法。方法的修饰符和字段略有不同,比如说 volatile 和 transient 不能用来修饰方法,再比如说方法的修饰符多了 synchronized、native、strictfp 和 abstract。 -![](https://img-blog.csdnimg.cn/img_convert/64a12c57dcd8d3283aede4753c75fca3.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/bytecode-fd434d5c-ffc6-4a24-9787-98e573035068.png) 下面这部分为构造方法,返回类型为 void,访问标志为 public。 @@ -450,4 +450,4 @@ private int age; 无论是从十六进制的字节码角度,还是 jclasslib 图形化查看反编译后的字节码的角度,也或者是今天这样从 javap 反编译后的角度,都能窥探出一些新的内容来! -初学者一开始接触字节码的时候会感觉比较头大,没关系,我当初也是这样,随着时间的推移,经验的积累,慢慢就好了,越往深处钻,就越能体会到那种“技术我有,雄霸天下”的感觉~ \ No newline at end of file +初学者一开始接触字节码的时候会感觉比较头大,没关系,我当初也是这样,随着时间的推移,经验的积累,慢慢就好了,越往深处钻,就越能体会到那种“技术我有,雄霸天下”的感觉~ diff --git a/docs/jvm/class-load.md b/docs/jvm/class-load.md index 9aa4b3275c0917842a07d17106cadbd6bdcdcb9d..48c98545a7a21dc6047dc34d898ad6986affe446 100644 --- a/docs/jvm/class-load.md +++ b/docs/jvm/class-load.md @@ -16,7 +16,7 @@ tag: Java 在诞生的时候喊出了一个非常牛逼的口号:“Write Once, Run Anywhere”,为了达成这个目的,Sun 公司发布了许多可以在不同平台(Windows、Linux)上运行的 Java 虚拟机(JVM)——负责载入和执行 Java 编译后的字节码。 -![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/class-load-7c6d4230-9154-4c7f-9ac1-122d39078442) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/class-load-01.png) 到底 Java 字节码是什么样子,我们借助一段简单的代码来看一看。 @@ -167,7 +167,7 @@ sun.misc.Launcher$ExtClassLoader@15db9742 如果以上三种类加载器不能满足要求的话,程序员还可以自定义类加载器(继承 `java.lang.ClassLoader` 类),它们之间的层级关系如下图所示。 -![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/class-load-fcef6ce9-5c54-4217-9681-8be69c456d8b) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/class-load-02.png) 这种层次关系被称作为**双亲委派模型**:如果一个类加载器收到了加载类的请求,它会先把请求委托给上层加载器去完成,上层加载器又会委托上上层加载器,一直到最顶层的类加载器;如果上层加载器无法完成类的加载工作时,当前类加载器才会尝试自己去加载这个类。 diff --git a/docs/jvm/compile-jdk.md b/docs/jvm/compile-jdk.md index 1b935c3d1fd27c0e5ede9de951c12a75cd8ad016..0a929c6a4e8b24daecb572834b09afdb3a4c447d 100644 --- a/docs/jvm/compile-jdk.md +++ b/docs/jvm/compile-jdk.md @@ -1,3 +1,13 @@ +--- +category: + - Java核心 + - JVM +tag: + - Java +--- + +# 自己编译JDK + 很多小伙伴们做`Java`开发,天天写`Java`代码,肯定离不开`Java`基础环境:`JDK`,毕竟我们写好的`Java`代码也是跑在`JVM`虚拟机上。 一般来说,我们学`Java`之前,第一步就是安装`JDK`环境。这个简单啊,我们一般直接把`JDK`从官网下载下来,安装完成,配个环境变量就可以愉快地使用了。 @@ -36,7 +46,7 @@ 一图胜千言,各平台上的编译器支持如下表所示,按平台选择即可: -![](https://upload-images.jianshu.io/upload_images/1179389-8fe4ece6f45ccc74.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-3b66d5b6-272f-47bd-88f7-47146a06ef06.png) ### **4、其他工具** @@ -75,7 +85,7 @@ `Mercurial`可以理解为和`Git`一样,是另外一种代码管理工具,安装好之后就有一个`hg`命令可用。 -![](https://upload-images.jianshu.io/upload_images/1179389-b038992018f648bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-cd8a19ba-e9f5-4a4a-a23c-17688f0f459d.png) 而`OpenJDK`的源码已经提前托管到`http://hg.openjdk.java.net/`。 @@ -96,7 +106,7 @@ 下载地址:`https://jdk.java.net/` -![](https://upload-images.jianshu.io/upload_images/1179389-7dc7742f5907f149.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-1bbbb1f8-da01-46e1-a793-487a25193c68.png) 选择你想要的版本下载即可。 @@ -118,27 +128,27 @@ **配置JDK 8完成:** -![](https://upload-images.jianshu.io/upload_images/1179389-3867d900e9a4c18c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-27593edc-03e2-4a42-baf3-ed5e5096b3cb.png) **配置JDK 11完成:** -![](https://upload-images.jianshu.io/upload_images/1179389-ecc8bbeb8f7f8a86.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-8526d944-a36e-4d37-93a0-9ad4ad53f927.png) **注:** 如果这一步出错,大概率是某个软件环境未装,或者即使装了,但版本不匹配,控制台打印日志里一般是会提醒的。 比如我在配置`JDK 8`的时候,就遇到了一个`errof:GCC compiler is required`的问题: -![](https://upload-images.jianshu.io/upload_images/1179389-6cde1ab51a34b6e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-2957399f-6451-46dc-a003-76e5159265e9.png) 明明系统里已经有编译器,但还是报这个错误。通过后来修改 `jdk源码根目录/common/autoconf/generated-configure.sh`文件,将相关的两行代码注释后就配置通过了 -![](https://upload-images.jianshu.io/upload_images/1179389-f07354003d229595.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-ffa10d36-3a77-48aa-ae0c-d3daf67f9a19.png) -![](https://upload-images.jianshu.io/upload_images/1179389-0e8c6c94255e19ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-a6f6e416-639e-4706-8b40-6152eb3cf85d.png) 配置完成,接下来开始执行真正的编译动作了! @@ -156,12 +166,12 @@ **JDK 8编译完成:** -![](https://upload-images.jianshu.io/upload_images/1179389-f61a82bb7b340811.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-89020f5a-0909-4c57-8c88-f655293a42a4.png) **JDK 11编译完成:** -![](https://upload-images.jianshu.io/upload_images/1179389-238728a22d2ae4bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-993fac94-2473-4f3b-9737-959510d2fe98.png) 从两张图的对比可以看出,编译`JDK 8`和`JDK 11`完成时在输出上还是有区别的。时间上的区别很大程度上来源于`JDK 11`的编译机配置要高不少。 @@ -184,7 +194,7 @@ 进入该目录后,可以输入`./java -version`命令验证: -![](https://upload-images.jianshu.io/upload_images/1179389-5449dc4bb0574327.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-f02dff40-f27e-476c-998b-bd6cdb5d3559.png) 其次,编译生成的成品`JDK`套装,可以在目录 @@ -194,7 +204,7 @@ 下找到,如图所示: -![](https://upload-images.jianshu.io/upload_images/1179389-1c9733b7a55a39fe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-1c781d34-776e-4acc-8d2b-b34bc59fda61.png) 其中: @@ -204,7 +214,7 @@ 进入`j2sdk-image`目录会发现,里面的内容和我们平时从网络上下载的成品`JDK`内容一致。 -![](https://upload-images.jianshu.io/upload_images/1179389-be394d2e97a6c8ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-7b7f147e-58c9-4eb5-b407-b8984cd72e1d.png) ### **2、JDK 11的编译输出** @@ -219,7 +229,7 @@ 下看到,进入该目录后,也可以输入`./java -version`命令验证: -![](https://upload-images.jianshu.io/upload_images/1179389-b2372c6a17726593.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-f9b55425-f308-44e8-8812-ac59b2707c81.png) 其次,编译生成的成品`JDK 11`套装,可以在目录 @@ -229,7 +239,7 @@ 下找到,如图所示: -![](https://upload-images.jianshu.io/upload_images/1179389-50d09e58e36b3aac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-4e96858f-f681-4498-b1c4-282d317a6a32.png) 其中`jdk`目录就是编译生成的成品`JDK 11`套装。 @@ -242,20 +252,20 @@ 新建一个最最基本的`Java`工程,比如命名为`JdkTest`,目的是把我们自己编译出的`JDK`给用上。 -![](https://upload-images.jianshu.io/upload_images/1179389-09ead6f932b19a36.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-2cf54b29-9b7e-46b2-8cde-4c36960aa09b.png) 我们点开`Project Structure`,选到`SDKs`选项,新添加上自己刚刚编译生成的JDK,并选为项目的JDK,看看是否能正常工作 -![](https://upload-images.jianshu.io/upload_images/1179389-b7f8a14909575248.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-ad8023d0-fbb7-48b1-856e-a8818677a0a5.png) -![](https://upload-images.jianshu.io/upload_images/1179389-bca2673d926753de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-b8d87f09-6178-44c7-9572-a2852e81318d.png) 点击确定之后,我们运行之: -![](https://upload-images.jianshu.io/upload_images/1179389-d11ded14bd13a8a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-3164cf31-8078-46d7-bee0-22e05b0c08de.png) 可以看到我们自己编译出的JDK已经用上了。 @@ -266,31 +276,31 @@ 我们继续在上一步`JdkTest`项目的`Project Structure` → `SDKs`里将`JDK`源码关联到自行下载的JDK源码路径上: -![](https://upload-images.jianshu.io/upload_images/1179389-538b9a08b4031a9a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-129ede68-c368-461e-92d6-38a8e5dee344.png) 这样方便我们对自己下载的`JDK源码`进行**阅读**、**调试**、**修改**、以及在源码里随意**做笔记**和**加注释**。 举个最简单的例子,比如我们打开`System.out.println()`这个函数的底层源码: -![](https://upload-images.jianshu.io/upload_images/1179389-12247e4b15ec0936.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-c406b2a2-208a-4a54-a869-b3f526e93ccd.png) 我们随便给它修改一下,加两行简单的标记,像这样: -![](https://upload-images.jianshu.io/upload_images/1179389-b271aef7ba3844f2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-2a46b215-04e5-458a-b475-4dc31d7fe326.png) 为了使我们新加的代码行生效,我们必须要重新去JDK源码的根目录中再次执行 `make images`重新编译生成JDK方可生效: -![](https://upload-images.jianshu.io/upload_images/1179389-5d35948c61ee8801.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-fd3cf88d-007e-4615-99b5-a3499c35ef40.png) 因为之前已经全量编译过了,所以再次`make`的时候增量编译一般很快。 重新编译之后,我们再次运行`JdkTest`项目,就可以看到改动的效果了: -![](https://upload-images.jianshu.io/upload_images/1179389-9e44c4851d71b82d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-33dc0de6-2690-4ba2-9fe7-0e450c44c07b.png) * * * @@ -305,14 +315,14 @@ 比如,还是以上面例子中最简单的`System.out.println()`源码为例,我们添加几行中文注释: -![](https://upload-images.jianshu.io/upload_images/1179389-0994ca44784b5558.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-d6a44833-b908-4824-8862-1679bfdddfa3.png) 这时候我们去JDK源码目录下编译会发现满屏类似这样的报错: > 错误: 编码 ascii 的不可映射字符 -![](https://upload-images.jianshu.io/upload_images/1179389-d830ae06a196161e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-ad0ca5a3-36c7-477d-bd58-d6731a87d762.png) 顿时有点懵,毕竟仅仅是加了几行注释。对于我们来说,源码里写点多行的中文注释基本是**刚需**,然而编译竟会报错,这还能不能让人愉快的玩耍了... 当时后背有点发凉。 @@ -325,12 +335,12 @@ `jdk源码根目录/make/common/SetupJavaCompilers.gmk`文件中有两处指定了`ascii`相关的编码方式: -![](https://upload-images.jianshu.io/upload_images/1179389-f8819768a06f1019.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-a86933af-f6d5-4d45-b4ca-33069a212c52.png) 于是尝试将这两处`-encoding ascii`的均替换成`-encoding utf-8`: -![](https://upload-images.jianshu.io/upload_images/1179389-31c43dadfdddaaec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/compile-jdk-c8117faf-d027-48d3-869b-32d0e98e8372.png) 然后再次执行`make images`编译,编译顺利通过! @@ -340,3 +350,7 @@ 这样后面不管是**阅读**、**调试**还是**定制**`JDK`源码都非常方便了。 +--- + +引用链接:https://segmentfault.com/a/1190000023251649 + diff --git a/docs/jvm/gc.md b/docs/jvm/gc.md index 6d2017e3c737faedd824c48c578fb3b9241ba826..01238406f9663d411b253be8460dc734c494c748 100644 --- a/docs/jvm/gc.md +++ b/docs/jvm/gc.md @@ -31,13 +31,13 @@ tag: 先创建一个字符串,这时候"jack"有一个引用,就是 m。 -![](https://upload-images.jianshu.io/upload_images/1179389-4582bb244165acc4.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-691109d2-bee4-4a79-8da6-87c5fd233f54.jpg) 然后将 m 设置为 null,这时候"jack"的引用次数就等于0了,在引用计数算法中,意味着这块内容就需要被回收了。 **m = null;** -![](https://upload-images.jianshu.io/upload_images/1179389-048b1138f853f7eb.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-74865618-4576-4f8b-baf3-17d6a71125b9.jpg) 引用计数算法是将垃圾回收分摊到整个应用程序的运行当中了,而不是在进行垃圾收集时,要挂起整个应用的运行,直到对堆中所有对象的处理都结束。因此,采用引用计数的垃圾收集不属于严格意义上的"Stop-The-World"的垃圾收集机制。 @@ -68,7 +68,7 @@ b = null; **2\. 相互引用** **3\. 置空各自的声明引用** -![](https://upload-images.jianshu.io/upload_images/1179389-86b2c41b63437f88.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-fe980c00-3605-4b5d-a711-7edbfd2c80b0.jpg) 我们可以看到,最后这2个对象已经不可能再被访问了,但由于他们相互引用着对方,导致它们的引用计数永远都不会为0,通过引用计数算法,也就永远无法通知GC收集器回收它们。 @@ -76,7 +76,7 @@ b = null; 可达性分析算法(Reachability Analysis)的基本思路是,通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时(即从 GC Roots 节点到该节点不可达),则证明该对象是不可用的。 -![](https://upload-images.jianshu.io/upload_images/1179389-696ce5e5d3727f0b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-1636ce77-77b3-4b10-b75a-c0c2d28912c5.jpg) 通过可达性算法,成功解决了引用计数所无法解决的问题-“循环依赖”,只要你无法与 GC Root 建立直接或间接的连接,系统就会判定你为可回收对象。那这样就引申出了另一个问题,哪些属于 GC Root。 @@ -89,7 +89,7 @@ b = null; * 方法区中常量引用的对象 * 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象 -![](https://upload-images.jianshu.io/upload_images/1179389-5b483f86d4aad226.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-6abf9f50-dc53-4e8f-a7f6-3e74df8803d6.jpg) 1、虚拟机栈(栈帧中的本地变量表)中引用的对象 此时的 s,即为 GC Root,当s置空时,localParameter 对象也断掉了与 GC Root 的引用链,将被回收。 @@ -141,7 +141,7 @@ s = null; 4、本地方法栈中引用的对象 任何 native 接口都会使用某种本地方法栈,实现的本地方法接口是使用 C 连接模型的话,那么它的本地方法栈就是 C 栈。当线程调用 Java 方法时,虚拟机会创建一个新的栈帧并压入 Java 栈。然而当它调用的是本地方法时,虚拟机会保持 Java 栈不变,不再在线程的 Java 栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。 -![](https://upload-images.jianshu.io/upload_images/1179389-71a5f9fe99025832.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-a138a4b4-56cb-4d6f-a65a-7f4259977476.jpg) ### 怎么回收垃圾 @@ -149,7 +149,7 @@ s = null; **标记 --- 清除算法** -![](https://upload-images.jianshu.io/upload_images/1179389-bafcd58836e2de69.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-2001e224-0f34-4429-bc89-a8fbe8ab271c.jpg) 标记清除算法(Mark-Sweep)是最基础的一种垃圾回收算法,它分为2部分,先把内存区域中的这些对象进行标记,哪些属于可回收标记出来,然后把这些垃圾拎出来清理掉。就像上图一样,清理掉的垃圾就变成未使用的内存区域,等待被再次使用。 @@ -159,7 +159,7 @@ s = null; **复制算法** -![](https://upload-images.jianshu.io/upload_images/1179389-129240ac460cb06e.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-a2b15e6f-6921-4710-bf76-77858df38c27.jpg) 复制算法(Copying)是在标记清除算法上演化而来,解决标记清除算法的内存碎片问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。保证了内存的连续可用,内存分配时也就不用考虑内存碎片等复杂情况,逻辑清晰,运行高效。 @@ -167,7 +167,7 @@ s = null; **标记整理算法** -![](https://upload-images.jianshu.io/upload_images/1179389-d931502c610a971c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-2d47a225-ad9d-4f15-9b4d-7dce9a693adf.jpg) 标记整理算法(Mark-Compact)标记过程仍然与标记 --- 清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,再清理掉端边界以外的内存区域。 @@ -177,7 +177,7 @@ s = null; ### 内存模型与回收策略 -![](https://upload-images.jianshu.io/upload_images/1179389-11711b193fa3c146.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/gc-59dddea1-b6bc-4fd4-bb79-d81adbdc7bed.jpg) Java 堆(Java Heap)是JVM所管理的内存中最大的一块,堆又是垃圾收集器管理的主要区域,这里我们主要分析一下 Java 堆的结构。 diff --git a/docs/jvm/how-jvm-run-zijiema-zhiling.md b/docs/jvm/how-jvm-run-zijiema-zhiling.md index 1498e1bd4b8303ddf7a5eb461c68a872e0b5c5ae..2b7abdc358ab5374403081099ab786e0477736b3 100644 --- a/docs/jvm/how-jvm-run-zijiema-zhiling.md +++ b/docs/jvm/how-jvm-run-zijiema-zhiling.md @@ -20,7 +20,7 @@ tag: 一个线程中的方法调用链可能会很长,很多方法都处于执行状态。对于执行引擎来说,在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧(Current Stack Frame),与这个栈帧相关联的方法成为当前方法。执行引擎运行的所有字节码指令对当前栈帧进行操作,在概念模型上,典型的栈帧结构如下图: -![](https://img-blog.csdnimg.cn/img_convert/0319e9d067853d3dc33ea392a7941be6.webp?x-oss-process=image/format,png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-a58ee82e-c0b0-4c06-9606-f7a0f0df0de9) #### 局部变量表 @@ -40,7 +40,7 @@ public class LocalVaraiablesTable { 然后用 Intellij IDEA 的 jclasslib 查看一下编译后的字节码文件 LocalVaraiablesTable.class。可以看到 `write()` 方法的 Code 属性中,Maximum local variables(局部变量表的最大容量)的值为 3。 -![](https://upload-images.jianshu.io/upload_images/1179389-83d2c9bab74251b6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-70ab6bf6-4fbb-4722-99b4-a93d5061630c.png) 按理说,局部变量表的最大容量应该为 2 才对,一个 age,一个 name,为什么是 3 呢? @@ -48,7 +48,7 @@ public class LocalVaraiablesTable { 点开 Code 属性,查看 LocalVaraiableTable 就可以看到详细的信息了。 -![](https://upload-images.jianshu.io/upload_images/1179389-81b7f1368e494908.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-e5e6037c-9be1-472f-8ab3-2754466e7828.png) 第 0 个是 this,类型为 LocalVaraiablesTable 对象;第 1 个是方法参数 age,类型为整形 int;第 2 个是方法内部的局部变量 name,类型为字符串 String。 @@ -97,15 +97,15 @@ public void solt() { 用 jclasslib 可以查看到,`solt()` 方法的 Maximum local variables 的值为 4。 -![](https://upload-images.jianshu.io/upload_images/1179389-93f5a356e356c2b6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-6734774b-376c-49bf-a915-508c7e829557.png) 为什么等于 4 呢?带上 this 也就 3 个呀? -![](https://upload-images.jianshu.io/upload_images/1179389-b0ebba7ff857d676.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-91ad04f8-1620-44c9-83d1-6fbd7860701a.png) 查看 LocalVaraiableTable 就明白了,变量 i 的下标为 3,也就意味着变量 d 占了两个槽。 -![](https://upload-images.jianshu.io/upload_images/1179389-dbb0621be3cf1a9a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-630b50e3-fc37-4748-8d20-852d5358f87a.png) #### 操作数栈 @@ -127,11 +127,11 @@ public class OperandStack { OperandStack 类共有 2 个方法,`test()` 方法中调用了 `add()` 方法,传递了 2 个参数。用 jclasslib 可以看到,`test()` 方法的 maximum stack size 的值为 3。 -![](https://upload-images.jianshu.io/upload_images/1179389-a3fc3ce51eecdbdd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-f790aa0f-d742-465b-91bf-5f143ee098c1.png) 这是因为调用成员方法的时候会将 this 和所有参数压入栈中,调用完毕后 this 和参数都会一一出栈。通过 「Bytecode」 面板可以查看到对应的字节码指令。 -![](https://upload-images.jianshu.io/upload_images/1179389-cbff77396db0e12f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-c37add5c-a74b-4bd6-8c8e-9085d9e6d374.png) - aload_0 用于将局部变量表中下标为 0 的引用类型的变量,也就是 this 加载到操作数栈中; - iconst_1 用于将整数 1 加载到操作数栈中; @@ -142,14 +142,14 @@ OperandStack 类共有 2 个方法,`test()` 方法中调用了 `add()` 方法 再来看一下 `add()` 方法的字节码指令。 -![](https://upload-images.jianshu.io/upload_images/1179389-1b9f4e45ca8fcacc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-49e3f396-7ea8-49f5-81d4-093b9bdfa453.png) - iload_1 用于将局部变量表中下标为 1 的 int 类型变量加载到操作数栈上(下标为 0 的是 this); - iload_2 用于将局部变量表中下标为 2 的 int 类型变量加载到操作数栈上; - iadd 用于 int 类型的加法运算; - ireturn 为返回值为 int 的方法返回指令。 -![](https://upload-images.jianshu.io/upload_images/1179389-1a3949544aced120.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-3ffdbe03-c0e4-49de-97a6-76666964a087.png) 操作数中的数据类型必须与字节码指令匹配,以上面的 iadd 指令为例,该指令只能用于整形数据的加法运算,它在执行的时候,栈顶的两个数据必须是 int 类型的,不能出现一个 long 型和一个 double 型的数据进行 iadd 命令相加的情况。 @@ -204,7 +204,7 @@ public class DynamicLinking { 用 jclasslib 看一下 main 方法的字节码指令。 -![](https://upload-images.jianshu.io/upload_images/1179389-6dce7f63885221ab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-93a21aaf-ff67-445d-8ddb-ac6f72fd9b25.png) - 第 1 行:new 指令创建了一个 Man 对象,并将对象的内存地址压入栈中。 - 第 2 行:dup 指令将栈顶的值复制一份并压入栈顶。因为接下来的指令 invokespecial 会消耗掉一个当前类的引用,所以需要复制一份。 @@ -559,7 +559,7 @@ Java 语言常被人们定义成「解释执行」的语言,但随着 JIT 以 无论是解释执行还是编译执行,无论是物理机还是虚拟机,对于应用程序,机器都不可能像人一样阅读、理解,然后获得执行能力。大部分的程序代码到物理机的目标代码或者虚拟机执行的指令之前,都需要经过下图中的各个步骤。下图中最下面的那条分支,就是传统编译原理中程序代码到目标机器代码的生成过程;中间那条分支,则是解释执行的过程。 -![](https://img-blog.csdnimg.cn/a87ea7b0dd7f4bdca22d8e6732f64ee8.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/how-jvm-run-zijiema-zhiling-3c8a0865-2a77-464e-8dd6-5616fd6a72d7.png) 如今,基于物理机、Java 虚拟机或者非 Java 的其它高级语言虚拟机的语言,大多都会遵循这种基于现代编译原理的思路,在执行前先对程序源代码进行词法分析和语法分析处理,把源代码转化为抽象语法树。对于一门具体语言的实现来说,词法分析、语法分析以至后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器去实现,这类代表是 C/C++。也可以为一个半独立的编译器,这类代表是 Java。又或者把这些步骤和执行全部封装在一个封闭的黑匣子中,如大多数的 JavaScript 执行器。 @@ -580,5 +580,5 @@ Java 编译器输出的指令流,基本上是一种基于栈的指令集架构 ---- -作者:BaronTalk -链接:https://juejin.cn/post/6844903871010045960 + +引用链接:https://juejin.cn/post/6844903871010045960 diff --git a/docs/jvm/hsdb.md b/docs/jvm/hsdb.md index 734ed12434bdb4ed18fdfc3125880ac18e8c983b..38b320d7bbfddddbf3e831bd1ff6309deca705a6 100644 --- a/docs/jvm/hsdb.md +++ b/docs/jvm/hsdb.md @@ -72,33 +72,33 @@ $ jps ### 可视化线程栈 -![](https://upload-images.jianshu.io/upload_images/1179389-07afdc3c2b66fa3d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-a606c6ac-1cfc-44c3-8fdf-e0eeeabbf05a.png) ### 对象直方图 `Tools -> Object Histogram`,我们可以通过对象直方图快速定位某个类型的对象的地址以供我们进一步分析 -![](https://upload-images.jianshu.io/upload_images/1179389-ec4b946a0804334e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-cf39737a-7d6a-42de-b843-123cba1f96aa.png) -![](https://upload-images.jianshu.io/upload_images/1179389-120d4d54c09cb697.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-974d211c-e627-40d6-af13-9560ebae0bfa.png) ### OOP信息 我们可以根据对象地址在 `Tools -> Inspector` 获取对象的在 JVM 层的实例 `instanceOopDesc` 对象,它包括对象头 `_mark` 和 `_metadata` 以及实例信息 -![](https://upload-images.jianshu.io/upload_images/1179389-0f5bcf523b13aadc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-026fb881-59a2-4e0f-ac4a-a2a7b505a707.png) ### 堆信息 我们可以通过 `Tools -> Heap Parameters` 获取堆信息,可以结合对象地址判断对象位置 -![](https://upload-images.jianshu.io/upload_images/1179389-a2b9e8c740a8b717.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-3baabaf0-1681-4443-b8db-ae08128744d6.png) ### 加载类列表 我们可以通过 `Tools -> Class Browser` 来获取所有加载类列表 -![](https://upload-images.jianshu.io/upload_images/1179389-413e8aa34bd714a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-7e4ebd1f-ba9c-4862-b4c3-574de5c30d6b.png) ### 元数据区 @@ -108,18 +108,18 @@ HotSpot VM 里有一套对象专门用来存放元数据,它们包括:  * `ConstantPool/ConstantPoolCache` 对象:每个 `InstanceKlass` 关联着一个 `ConstantPool`,作为该类型的运行时常量池。这个常量池的结构跟 Class 文件里的常量池基本上是对应的 -![](https://upload-images.jianshu.io/upload_images/1179389-fe2110ec3400736a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-07d80d18-be4e-4861-bea3-291eea0ff262.png) -![](https://upload-images.jianshu.io/upload_images/1179389-2067a77695ea91d5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-b7b0ebed-cd38-42b7-bebc-41090409a1db.png) * `Method` 对象,用来描述 Java 方法的总体信息,如方法入口地址、调用/循环计数器等等 * `ConstMethod` 对象,记录着 Java 方法的不变的描述信息,包括方法名、方法的访问修饰符、**字节码**、行号表、局部变量表等等。**注意,字节码指令被分配在 `constMethodOop` 对象的内存区域的末尾** * `MethodData` 对象,记录着 Java 方法执行时的 profile 信息,例如某方法里的某个字节码之类是否从来没遇到过 null,某个条件跳转是否总是走同一个分支,等等。这些信息在解释器(多层编译模式下也在低层的编译生成的代码里)收集,然后供给 HotSpot Server Compiler 用于做激进优化。 -![](https://upload-images.jianshu.io/upload_images/1179389-06e56c814c156cfb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-59231922-9ce3-4107-ab1a-b33818cbab96.png) -![](https://upload-images.jianshu.io/upload_images/1179389-539d3ef606a97139.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-85c6fca7-2d1f-4194-bc07-fd1e2ab18632.png) * `Symbol` 对象,对应 Class 文件常量池里的 `JVM_CONSTANT_Utf8` 类型的常量。有一个 VM 全局的 `SymbolTable` 管理着所有 `Symbol`。`Symbol` 由所有 Java 类所共享。 @@ -159,23 +159,23 @@ class VMShow { 首先查看对象直方图可以找到三个 VMShow 对象 -![](https://upload-images.jianshu.io/upload_images/1179389-48e27aeb30f47103.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-e5f0f200-83fd-4529-b5d6-416f9a6f626b.png) 那么如何确定这三个地址分别属于哪些变量呢?首先找静态变量,它在 JDK8 中是在 Class 对象中的,因此我们可以找它们的反向指针,如果是`java.lang.Class` 的那么就是静态变量 -![](https://upload-images.jianshu.io/upload_images/1179389-2b4087bd358a0eb5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-301ebfc3-c2c4-49de-946a-5d2f1660e669.png) 我们可以从 ObjTest 的 `instanceKlass` 中的镜像找到 class 对象来验证是否是该对象的 class -![](https://upload-images.jianshu.io/upload_images/1179389-95cab9181b8b77af.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-f22359ab-b066-405f-a754-197ccbd36884.png) 那么成员变量和局部变量如何区分呢?成员变量会被类实例引用,而局部变量地址则在会被被放在栈区 -![](https://upload-images.jianshu.io/upload_images/1179389-80bced631b4dafcf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-51cb7321-fb7a-42b0-9321-edd410e3d328.png) 那么局部变量的反向指针都是 null,怎么确定它就被栈区所引用呢?我们可以看可视化线程栈 -![](https://upload-images.jianshu.io/upload_images/1179389-9b97606de3b61531.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-51fb09f4-06d7-4518-8038-5dd69d765862.png) ### 分析字符串字面量存储区域 @@ -198,7 +198,7 @@ public class StringTest { 2. 打开对象直方图发现只有 1 个 `a` 的字符串对象 -![](https://upload-images.jianshu.io/upload_images/1179389-946aec17f0649e1c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-b5631e70-be3a-48de-99be-4468632d23e0.png) 3. 查找 StringTable 中 `a` 的对象地址 @@ -208,7 +208,7 @@ jseval "st = sa.vm.stringTable;st.stringsDo(function (s) { if (sapkg.oops.OopUti 可以根据需要改变 `matches` 中的值来匹配 -![](https://upload-images.jianshu.io/upload_images/1179389-27e18d823a9fbd3d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-76084b8d-6134-4866-8891-c24a43a3b836.png) 可以看到这个对象地址就是 StringTable 中引用的地址 @@ -216,7 +216,7 @@ jseval "st = sa.vm.stringTable;st.stringsDo(function (s) { if (sapkg.oops.OopUti 5. 重新使用对象直方图查看 String 值 -![](https://upload-images.jianshu.io/upload_images/1179389-c6ce35bebc51e557.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-f3c35027-2fe1-4b18-8a1c-b7243a9b5149.png) 这里有5个值,`ab` 有3个: @@ -231,13 +231,13 @@ jseval "st = sa.vm.stringTable;st.stringsDo(function (s) { if (sapkg.oops.OopUti ``` -![](https://upload-images.jianshu.io/upload_images/1179389-2953df01d3c87685.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-f07a9fc8-5744-4859-9df9-c3a1016e936a.png) 那么运行时常量池中存放的是哪些呢?实际上它和 StringTable 一样是这些对象的引用,只不过 StringTable 是全局共享的,而运行时常量池只有该类的一些字面量。我们通过加载类列表可以查看 -![](https://upload-images.jianshu.io/upload_images/1179389-2dd5e0ac29c0f3a5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-25fa5e06-0250-424b-8b05-aea770e80963.png) -![](https://zzcoder.oss-cn-hangzhou.aliyuncs.com/jvm/HSDB-20.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-88e8c10d-e09c-4a74-95e6-e5b21577459f.png) ### 分析String.intern @@ -328,22 +328,22 @@ public class StringInternTest { jseval "st = sa.vm.stringTable;st.stringsDo(function (s) { if (sapkg.oops.OopUtilities.stringOopToString(s).matches('^(he|llo|hello|1|2|12)')) {print(s + ': ');s.printValueOn(java.lang.System.out); println('')}})" ``` -![](https://upload-images.jianshu.io/upload_images/1179389-fd5799daae6fb942.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-ca5d06a0-1690-4a8f-98cb-aa6bd7800afe.png) 但是 `hello` 对象还是存在的(new) -![](https://upload-images.jianshu.io/upload_images/1179389-da8c4df5133fccd3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-85253e10-d0c2-442b-a26b-91b1b2588f1c.png) 接着执行 s1.intern 会将 `hello` 对象的地址放入 StringTable -![](https://upload-images.jianshu.io/upload_images/1179389-d888e688976bae33.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-801d35f2-0c8a-4699-afbf-057c1e6cac6c.png) 再执行 `String s2="hello";` 会发现 `hello` 对象仍然只有一个,都指向同一个。 而继续在 6 打断点,即执行完 `String s4 = "12";`,因为 `12` 不在字符串常量池,那么会新建一个 `12`的实例,并让字符串常量池引用它,这样会发现就有两个 `12` 了 -![](https://upload-images.jianshu.io/upload_images/1179389-7abae26e2d2e6a6b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/hsdb-47a42bfa-7645-4c9b-bcd8-aeabea1ae44f.png) --- ->参考链接:https://zzcoder.cn/2019/12/06/HSDB%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E6%88%98/ \ No newline at end of file +>参考链接:https://zzcoder.cn/2019/12/06/HSDB%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E6%88%98/ diff --git a/docs/jvm/jit.md b/docs/jvm/jit.md index 60e8004e00dcb950db6878118834f506d22328cf..07849347b71a707211b9ec21208d44812a9ea648 100644 --- a/docs/jvm/jit.md +++ b/docs/jvm/jit.md @@ -1,3 +1,13 @@ +--- +category: + - Java核心 + - JVM +tag: + - Java +--- + +# Java即时编译(JIT)器原理解析及实践 + ## 一、导读 常见的编译型语言如C++,通常会把代码直接编译成CPU所能理解的机器码来运行。而Java为了实现“一次编译,处处运行”的特性,把编译的过程分成两部分,首先它会先由javac编译成通用的中间形式——字节码,然后再由解释器逐条将字节码解释为机器码来执行。所以在性能上,Java通常不如C++这类编译型语言。 @@ -12,7 +22,7 @@ Java的执行过程整体可以分为两个部分,第一步由javac将源码 怎么样才会被认为是热点代码呢?JVM中会设置一个阈值,当方法或者代码块的在一定时间内的调用次数超过这个阈值时就会被编译,存入codeCache中。当下次执行时,再遇到这段代码,就会从codeCache中读取机器码,直接执行,以此来提升程序运行的性能。整体的执行过程大致如下图所示: -![image](https://upload-images.jianshu.io/upload_images/1179389-3126df91fd5df8e4.png@648w_454h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-9a62fc02-1a6a-451e-bb2b-19fc086d5be0.png) ### 1\. JVM中的编译器 @@ -40,7 +50,7 @@ Ideal Graph的构建是在解析字节码的时候,根据字节码中的指令 无论是否进行全局优化,Ideal Graph都会被转化为一种更接近机器层面的MachNode Graph,最后编译的机器码就是从MachNode Graph中得的,生成机器码前还会有一些包括寄存器分配、窥孔优化等操作。关于Ideal Graph和各种全局的优化手段会在后面的章节详细介绍。Server Compiler编译优化的过程如下图所示: -![image](https://upload-images.jianshu.io/upload_images/1179389-9fe7776de5303554.png@823w_864h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-f4d1b763-be02-4bb2-ab0e-45b1f0eb9550.png) **Graal Compiler** @@ -66,7 +76,7 @@ profiling就是收集能够反映程序执行状态的数据。其中最基本 通常情况下,C2代码的执行效率要比C1代码的高出30%以上。C1层执行的代码,按执行效率排序从高至低则是1层>2层>3层。这5个层次中,1层和4层都是终止状态,当一个方法到达终止状态后,只要编译后的代码并没有失效,那么JVM就不会再次发出该方法的编译请求的。服务实际运行时,JVM会根据服务运行情况,从解释执行开始,选择不同的编译路径,直到到达终止状态。下图中就列举了几种常见的编译路径: -![image](https://upload-images.jianshu.io/upload_images/1179389-9f661f22d9141930.png@863w_680h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-a6cebc82-ed4d-4b6d-892a-c5b245d227ab.png) * 图中第①条路径,代表编译的一般情况,热点方法从解释执行到被3层的C1编译,最后被4层的C2编译。 * 如果方法比较小(比如Java服务中常见的getter/setter方法),3层的profiling没有收集到有价值的数据,JVM就会断定该方法对于C1代码和C2代码的执行效率相同,就会执行图中第②条路径。在这种情况下,JVM会在3层编译之后,放弃进入C2编译,直接选择用1层的C1编译运行。 @@ -82,7 +92,7 @@ Java虚拟机根据方法的调用次数以及循环回边的执行次数来触 循环回边 -``` +```java public void nlp(Object obj) { int sum = 0; for (int i = 0; i < 200; i++) { @@ -179,7 +189,7 @@ Plain Text DeadCodeElimination -``` +```java public void DeadCodeElimination{ int a = 2; int b = 0 @@ -212,7 +222,7 @@ add(a,b) DeadCodeElimination -``` +```java public void DeadCodeElimination{ int a = 1; int b = 0; @@ -229,7 +239,7 @@ public void DeadCodeElimination{ HIR是由很多基本块(Basic Block)组成的控制流图结构,每个块包含很多SSA形式的指令。基本块的结构如下图所示: -![image](https://upload-images.jianshu.io/upload_images/1179389-11a9e073b3bcb0b7.png@262w_611h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-037b406d-1040-4bf8-976c-abf14a92402d.png) 其中,predecessors表示前驱基本块(由于前驱可能是多个,所以是BlockList结构,是多个BlockBegin组成的可扩容数组)。同样,successors表示多个后继基本块BlockEnd。除了这两部分就是主体块,里面包含程序执行的指令和一个next指针,指向下一个执行的主体块。 @@ -257,7 +267,7 @@ C2编译器中的Ideal Graph采用的是一种名为Sea-of-Nodes中间表达形 example -``` +```java public static int foo(int count) { int sum = 0; for (int i = 0; i < count; i++) { @@ -270,7 +280,7 @@ public static int foo(int count) { 对应的IR图如下所示: -![image](https://upload-images.jianshu.io/upload_images/1179389-d8aead91e1ba9a44.png@1368w_1260h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-f96da42a-568b-45ba-bed1-f4238ac32e14.png) 图中若干个顺序执行的节点将被包含在同一个基本块之中,如图中的B0、B1等。B0基本块中0号Start节点是方法入口,B3中21号Return节点是方法出口。红色加粗线条为控制流,蓝色线条为数据流,而其他颜色的线条则是特殊的控制流或数据流。被控制流边所连接的是固定节点,其他的则是浮动节点(浮动节点指只要能满足数据依赖关系,可以放在不同位置的节点,浮动节点变动的这个过程称为Schedule)。 @@ -284,7 +294,7 @@ Ideal Graph是SSA IR。 由于没有变量的概念,这会带来一个问题 example -``` +```java int test(int x) { int a = 0; if(x == 1) { @@ -299,7 +309,7 @@ int a = 0; 为了解决这个问题,就引入一个Phi Nodes的概念,能够根据不同的执行路径选择不同的值。于是,上面这段代码可以表示为下面这张图: -![image](https://upload-images.jianshu.io/upload_images/1179389-3e627d4775f58424.png@631w_930h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-fb8b2bac-a7b9-45eb-bd28-05e35cf043ae.png) Phi Nodes中保存不同路径上包含的所有值,Region Nodes根据不同路径的判断条件,从Phi Nodes取得当前执行路径中变量应该赋予的值,带有Phi节点的SSA形式的伪代码如下: @@ -348,7 +358,7 @@ Java服务中存在大量getter/setter方法,如果没有方法内联,在调 方法内联的过程 -``` +```java public static boolean flag = true; public static int value0 = 0; public static int value1 = 1; @@ -370,11 +380,11 @@ public static int bar(boolean flag) { bar方法的IR图: -![image](https://upload-images.jianshu.io/upload_images/1179389-01e951d9001258a7.png@794w_480h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-04ca4a7e-46e7-4782-bb43-333aea31ed57.png) 内联后的IR图: -![image](https://upload-images.jianshu.io/upload_images/1179389-ab152f0a9b85b528.png@802w_1202h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-4bf4d190-7fd2-4542-b948-0c85ee6963d2.png) 内联不仅将被调用方法的IR图节点复制到调用者方法的IR图中,还要完成其他操作。 @@ -390,7 +400,7 @@ bar方法的IR图: 可以通过虚拟机参数-XX:MaxInlineLevel调整内联的层数,以及1层的直接递归调用(可以通过虚拟机参数-XX:MaxRecursiveInlineLevel调整)。一些常见的内联相关的参数如下表所示: -![image](https://upload-images.jianshu.io/upload_images/1179389-b806c277c64a7bc5.png@1350w_612h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-48e4ff65-07ec-487e-8b08-2f8fed1e56bd.png) **虚函数内联** @@ -400,7 +410,7 @@ C2编译器已经足够智能,能够检测这种情况并会对虚调用进行 virtual call -``` +```java public class SimpleInliningTest { public static void main(String[] args) throws InterruptedException { @@ -449,7 +459,7 @@ public class SimpleInliningTest 多实现的虚调用 -``` +```java public class SimpleInliningTest { public static void main(String[] args) throws InterruptedException { @@ -515,7 +525,7 @@ Graal编译器针对这种情况,会去收集这部分执行的信息,比如 逃逸分析通常是在方法内联的基础上进行的,即时编译器可以根据逃逸分析的结果进行诸如锁消除、栈上分配以及标量替换的优化。下面这段代码的就是对象未逃逸的例子: -``` +```java pulbic class Example{ public static void main(String[] args) { example(); @@ -553,7 +563,7 @@ pulbic class Example{ 标量替换 -``` +```java public class Example{ @AllArgsConstructor class Cat{ @@ -570,7 +580,7 @@ public class Example{ 经过逃逸分析,cat对象未逃逸出example()的调用,因此可以对聚合量cat进行分解,得到两个标量age和weight,进行标量替换后的伪代码: -``` +```java public class Example{ @AllArgsConstructor class Cat{ @@ -602,7 +612,7 @@ public class Example{ 循环展开 -``` +```java public void loopRolling(){ for(int i = 0;i<200;i++){ delete(i); @@ -615,7 +625,7 @@ public void loopRolling(){ 循环展开 -``` +```java public void loopRolling(){ for(int i = 0;i<200;i+=5){ delete(i); @@ -636,7 +646,7 @@ public void loopRolling(){ 循环分离 -``` +```java int a = 10; for(int i = 0;i<10;i++){ b[i] = x[i] + x[a]; @@ -649,7 +659,7 @@ for(int i = 0;i<10;i++){ 循环分离 -``` +```java b[0] = x[0] + 10; for(int i = 1;i<10;i++){ b[i] = x[i] + x[i-1]; @@ -698,13 +708,13 @@ y1=x1*3 经过强度削减后得到 y1=(x1<<1)+x1 通过增加-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining -XX:+PrintCodeCache -XX:+PrintCodeCacheOnCompilation -XX:+TraceClassLoading -XX:+LogCompilation -XX:LogFile=LogPath参数可以输出编译、内联、codeCache信息到文件。但是打印的编译日志多且复杂很难直接从其中得到信息,可以使用JITwatch的工具来分析编译日志。JITwatch首页的Open Log选中日志文件,点击Start就可以开始分析日志。 -![image](https://upload-images.jianshu.io/upload_images/1179389-6f00cfb06f13f05b.png@3360w_2099h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-82ee887c-af7d-48d7-88a0-28960e564d4a.png) -![image](https://upload-images.jianshu.io/upload_images/1179389-8adb46d70ada91b6.png@3360w_2033h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-6158d832-9a0d-4af0-96ff-bf216a9cd5c6.png) 如上图所示,区域1中是整个项目Java Class包括引入的第三方依赖;区域2是功能区Timeline以图形的形式展示JIT编译的时间轴,Histo是直方图展示一些信息,TopList里面是编译中产生的一些对象和数据的排序,Cache是空闲codeCache空间,NMethod是Native方法,Threads是JIT编译的线程;区域3是JITwatch对日志分析结果的展示,其中Suggestions中会给出一些代码优化的建议,举个例子,如下图中: -![image](https://upload-images.jianshu.io/upload_images/1179389-4a2c46878663f5b7.png@1920w_218h_80q?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/jit-04b2d9ea-7add-4ee5-bf72-61a6bbaa58cf.png) 我们可以看到在调用ZipInputStream的read方法时,因为该方法没有被标记为热点方法,同时又“太大了”,导致无法被内联到。使用-XX:CompileCommand中inline指令可以强制方法进行内联,不过还是建议谨慎使用,除非确定某个方法内联会带来不少的性能提升,否则不建议使用,并且过多使用对编译线程和codeCache都会带来不小的压力。 @@ -738,4 +748,6 @@ Graal编译器的优化方式更加激进,因此在启动时会进行更多的 本文主要介绍了JIT即时编译的原理以及在美团一些实践的经验,还有最前沿的即时编译器的使用效果。作为一项解释型语言中提升性能的技术,JIT已经比较成熟了,在很多语言中都有使用。对于Java服务,JVM本身已经做了足够多,但是我们还应该不断深入了解JIT的优化原理和最新的编译技术,从而弥补JIT的劣势,提升Java服务的性能,不断追求卓越。 -原文链接:https://tech.meituan.com/2020/10/22/java-jit-practice-in-meituan.html \ No newline at end of file +----- + +原文链接:https://tech.meituan.com/2020/10/22/java-jit-practice-in-meituan.html diff --git a/docs/jvm/neicun-jiegou.md b/docs/jvm/neicun-jiegou.md index 662a1bc31287ee3ffe4a659dd67f5712ef436d21..bb9d7c8d6bb3b465e17538b9a006841c0c0e05a0 100644 --- a/docs/jvm/neicun-jiegou.md +++ b/docs/jvm/neicun-jiegou.md @@ -10,7 +10,7 @@ tag: 在谈 JVM 内存区域划分之前,我们先来看一下 Java 程序的具体执行过程,我画了一幅图。 -![](https://img-blog.csdnimg.cn/img_convert/77f1fa00cdd92c77330538642d9ca3c4.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/neicun-jiegou-dac0f4c1-8a7e-4309-a599-5664cdaf5016.png) Java 源代码文件经过编译器编译后生成字节码文件,然后交给 JVM 的类加载器,加载完毕后,交给执行引擎执行。在整个执行的过程中,JVM 会用一块空间来存储程序执行期间需要用到的数据,这块空间一般被称为运行时数据区,也就是常说的 JVM 内存。 @@ -28,7 +28,7 @@ Java 源代码文件经过编译器编译后生成字节码文件,然后交给 根据第二章 Java 虚拟机结构中的规定,运行时数据区可以分为以下几个部分,见下图。 -![](https://img-blog.csdnimg.cn/img_convert/ed3ca24f1f857bf23a9b5c061535d258.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/neicun-jiegou-e33179f3-275b-44c9-87f6-802198f8f360.png) ### 01、程序计数器 @@ -51,7 +51,7 @@ Java 虚拟机栈中是一个个栈帧,每个栈帧对应一个被调用的方 栈帧包含以下 5 个部分,见下图。 -![](https://img-blog.csdnimg.cn/img_convert/2e727f1048988c8ce7e6ae46b08dfb54.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/neicun-jiegou-4ea2a60a-05df-4ed1-8109-99ae23acefd1.png) [Java 虚拟机栈](https://tobebetterjavaer.com/jvm/how-jvm-run-zijiema-zhiling.md) @@ -100,4 +100,4 @@ JDK 8 的时候,HotSpot 移除了永久代,也就是说方法区不存在了 第一,永久代放在 Java 虚拟机中,就会受到 Java 虚拟机内存大小的限制,而元空间使用的是本地内存,也就脱离了 Java 虚拟机内存的限制。 -第二,JDK 8 的时候,在 HotSpot 中融合了 JRockit 虚拟机,而 JRockit 中并没有永久代的概念,因此新的 HotSpot 就没有必要再开辟一块空间来作为永久代了。 \ No newline at end of file +第二,JDK 8 的时候,在 HotSpot 中融合了 JRockit 虚拟机,而 JRockit 中并没有永久代的概念,因此新的 HotSpot 就没有必要再开辟一块空间来作为永久代了。 diff --git a/docs/jvm/problem-tools.md b/docs/jvm/problem-tools.md index 6b59810a1e834f5c20ef58f5b511878b8e3b49b3..b1f76cbd59cedc51b5c374b0ea03b2ef555ddc6e 100644 --- a/docs/jvm/problem-tools.md +++ b/docs/jvm/problem-tools.md @@ -12,7 +12,7 @@ tag: 在JDK的bin目录下有很多命令行工具: -![image](https://upload-images.jianshu.io/upload_images/1179389-6298ada851edf7c6.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-547b1b2c-9fb4-4d1d-9c72-013ec210f6a5.jpg)   我们可以看到各个工具的大小基本上都稳定在27kb左右,这个不是JDK开发团队刻意为之的,而是因为这些工具大多数是 `jdk\lib\tools.jar` 类库的一层薄包装而已,他们的主要功能代码是在tools类库中实现的。 @@ -50,21 +50,21 @@ JAVA Dump就是虚拟机运行时的快照,将虚拟机运行时的状态和 显示当前所有java进程pid的命令,我们可以通过这个命令来查看到底启动了几个java进程(因为每一个java程序都会独占一个java虚拟机实例),不过jps有个缺点是只能显示当前用户的进程id,要显示其他用户的还只能用linux的ps命令。 -![image](https://upload-images.jianshu.io/upload_images/1179389-2d5d658c8b8db0b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-2017daf6-832a-4673-b776-ad3380e47402.png) 执行jps命令,会列出所有正在运行的java进程,其中jps命令也是一个java程序。前面的数字就是进程的id,这个id的作用非常大,后面会有相关介绍。 **jps -help:** -![image](https://upload-images.jianshu.io/upload_images/1179389-99d21062099dd578.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-031be661-e47e-44f0-9e33-34368b187662.png) **jps -l** 输出应用程序main.class的完整package名或者应用程序jar文件完整路径名 -![image](https://upload-images.jianshu.io/upload_images/1179389-d9f3ff6819b15a66.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-0ccc96dc-8053-4222-9824-b116f02776a4.png) **jps -v** 输出传递给JVM的参数 -![image](https://upload-images.jianshu.io/upload_images/1179389-3bcfc37630242cb0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-059a3285-4a01-4f7a-a6ed-1cc5dcbf3f18.png) **jps失效** @@ -87,7 +87,7 @@ java程序启动后,会在目录/tmp/hsperfdata_{userName}/下生成几个文 主要用于生成指定进程当前时刻的线程快照,线程快照是当前java虚拟机每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致长时间等待。 -![image](https://upload-images.jianshu.io/upload_images/1179389-5f09162f867d044e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-e80d0925-2dcf-4204-b46d-47312df2a673.png) **3、jmap** @@ -97,21 +97,21 @@ java程序启动后,会在目录/tmp/hsperfdata_{userName}/下生成几个文 jmap的用法摘要: -![image](https://upload-images.jianshu.io/upload_images/1179389-ef4aa428f2519317.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-96a70bab-5cee-4068-8ccb-1d35124abeea.png) **1、`jmap pid`** -![image](https://upload-images.jianshu.io/upload_images/1179389-b98c8d50df75dff0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-38d5c9da-e433-43d2-b1bc-3f3634e05497.png) 打印的信息分别为:共享对象的起始地址、映射大小、共享对象路径的全程。 **2、`jmap -heap pid`:查看堆使用情况** - ![image](https://upload-images.jianshu.io/upload_images/1179389-e3294292dc504803.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-75acf4c8-393d-43d1-b208-04de1f0ba6bd.png) **3、`jmap -histo pid`:查看堆中对象数量和大小** -**![image](https://upload-images.jianshu.io/upload_images/1179389-b5c31231270ec757.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示")** +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-5e42fe47-e1e6-4649-acb5-e17bd277a771.png) 打印的信息分别是:序列号、对象的数量、这些对象的内存占用大小、这些对象所属的类的全限定名 @@ -141,7 +141,7 @@ count:打印次数 **1、jstat -gc PID 5000 20** -![image](https://upload-images.jianshu.io/upload_images/1179389-d438cd37f68605c8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-3f71397d-3ff6-430d-adf4-ff5ab9f111d5.png) S0C:年轻代第一个survivor的容量(字节) @@ -173,7 +173,7 @@ FGCT:从应用程序启动到采样时老年代中GC所使用的时间(单 **2、jstat -gcutil PID 5000 20** -![image](https://upload-images.jianshu.io/upload_images/1179389-a210f6badcc528ed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-c2a84c1d-e853-482a-88a5-27ef39da66a0.png) s0:年轻代中第一个survivor已使用的占当前容量百分比 @@ -193,7 +193,7 @@ P:永久代中已使用的占当前容量百分比 **jhat heapdump** -![image](https://upload-images.jianshu.io/upload_images/1179389-83746a41d4bf74d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-fd76ac30-53a5-4549-8206-18283f330758.png) 这个命令将heapdump文件转换成html格式,并且启动一个http服务,默认端口为7000。 @@ -201,7 +201,7 @@ P:永久代中已使用的占当前容量百分比 下面我们来访问下:ip:port -![image](https://upload-images.jianshu.io/upload_images/1179389-cf3e93133f846884.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-059e61f1-8263-4ee0-b36b-f117ecaf0a07.png) ## 6、jinfo @@ -219,15 +219,15 @@ jinfo可以用来查看正在运行的java运用程序的扩展参数,甚至 下面的命令显示了新生代对象晋升到老年代对象的最大年龄。在运行程序运行时并没有指定这个参数,但是通过jinfo,可以查看这个参数的当前的值。 -![image](https://upload-images.jianshu.io/upload_images/1179389-31d29381b1ed517c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-f37517b7-20b4-4243-ae03-d41126ae43e5.png) 下面的命令显示是否打印gc详细信息: -![image](https://upload-images.jianshu.io/upload_images/1179389-4cbebf30779aa5ee.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-86c5ace2-7377-4d5a-a780-0a194e14c9a0.png) 下面的命令在运用程序运行时动态打开打印详细gc信息开关: -![image](https://upload-images.jianshu.io/upload_images/1179389-6d011dce3e04c0a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-d258d260-65eb-48f9-8585-6bed74de5a47.png) 注意事项:jinfo虽然可以在java程序运行时动态地修改虚拟机参数,但并不是所有的参数都支持动态修改。 @@ -236,11 +236,11 @@ jinfo可以用来查看正在运行的java运用程序的扩展参数,甚至 在JDK 1.7之后,新增了一个命令行工具jcmd。它是一个多功能工具,可以用来导出堆,查看java进程,导出线程信息,执行GC等。jcmd拥有jmap的大部分功能,Oracle官方建议使用jcmd代替jmap。 使用 jcmd -l 命令列出当前运行的所有虚拟机,示例: -![image](https://upload-images.jianshu.io/upload_images/1179389-428e5bb14754ca0c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-4fa6915b-d39c-4d6d-a6e7-edc989cac76f.png) 针对每一个虚拟机,可以使用help命令列出该虚拟机支持的所有命令,示例: -![image](https://upload-images.jianshu.io/upload_images/1179389-52c559995e3fbb49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-219b7cac-c9a9-4d47-8ecf-93a4a04fc1db.png) 子命令含义: @@ -264,7 +264,7 @@ jinfo可以用来查看正在运行的java运用程序的扩展参数,甚至 示例: -![image](https://upload-images.jianshu.io/upload_images/1179389-9225121e737ab406.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-b0742677-4ad0-4fd3-b985-054238af8865.png) ## 8、可视化监控工具(JConsole、JVisualVM) @@ -274,11 +274,11 @@ JVisualVM比JConsole更强大:支持对CPU、内存运行进行采样、配置 JConsole监控页面示例: -![image](https://upload-images.jianshu.io/upload_images/1179389-92e66778004bf548.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-7fa6b7b2-28bf-46cb-8d52-5fe3cb75240a.png) JVisualVM监控页面示例: -![image](https://upload-images.jianshu.io/upload_images/1179389-57562c975c5c0a24.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击全屏显示") +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-dca6e1d0-f345-4e21-83b3-e0cf82e3d79a.png) ## 其他工具  @@ -325,7 +325,7 @@ strace:跟踪程序运行过程发起的系统调用 https://fastthread.io:线程栈分析的网站 -![](https://upload-images.jianshu.io/upload_images/1179389-c82f746ad11b7f13.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/problem-tools-6d57b323-9665-4453-9fee-ea3111ad8629.png) ## 上问题排查思路(八股) @@ -339,4 +339,4 @@ CPU使用情况:top 命令 Java程序问题分析:jmap 分析堆内存、jstack 分析线程栈等,见前文。 -原文链接:https://www.cnblogs.com/z-sm/p/6745375.html \ No newline at end of file +原文链接:https://www.cnblogs.com/z-sm/p/6745375.html diff --git a/docs/jvm/tujie-gc.md b/docs/jvm/tujie-gc.md index fa83c91f2726e841d537c6b3c145931d05109336..09cf3412ee72bdafd37d103e0044b371845b259a 100644 --- a/docs/jvm/tujie-gc.md +++ b/docs/jvm/tujie-gc.md @@ -16,27 +16,27 @@ Java 语言出来之前,大家都在拼命的写 C 或者 C++ 的程序,此 垃圾回收的第一步是标记。垃圾回收器此时会找出内存哪些在使用中,哪些不是。 -![](https://upload-images.jianshu.io/upload_images/1179389-06e52d190ca89579.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-9858785a-c6aa-4d6d-a6cd-640d24dd27d0.png) 上图中,蓝色表示已引用对象,橙色表示未引用对象。垃圾回收器要检查完所有的对象,才能知道哪些有被引用,哪些没。如果系统里所有的对象都要检查,那这一步可能会相当耗时间。 垃圾回收的第二步是清除,这一步会删掉标记出的未引用对象。 -![](https://upload-images.jianshu.io/upload_images/1179389-b904f98d9c3a4097.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-768f5a2c-6c81-4f76-b847-a41cc8413228.png) 内存分配器会保留指向可用内存中的引用,以分配给新的对象。 垃圾回收的第三步是压缩,为了提升性能,删除了未引用对象后,还可以将剩下的已引用对象放在一起(压缩),这样就能更简单快捷地分配新对象了。 -![](https://upload-images.jianshu.io/upload_images/1179389-841ed7d6d46c1a60.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-989889b6-adb4-4277-8c67-73d76658f744.png) 之前提到过,逐一标记和压缩  Java 虚拟机中的所有对象非常低效:分配的对象越多,垃圾回收需要的时间就越久。不过,根据统计,大部分的对象,其实用没多久就不用了。 来看个例子吧。下图中,竖轴代表已分配的字节,而横轴代表程序的运行时间。 -![](https://upload-images.jianshu.io/upload_images/1179389-440e4e7cffe1297c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-24b154be-4ad0-4cc7-87e9-a3035bc9e3c5.png) 可见,存活(没被释放)的对象随着运行时间越来越少。图中左侧的峰值,也表明了大部分对象其实都挺短命的。 @@ -47,7 +47,7 @@ Java 语言出来之前,大家都在拼命的写 C 或者 C++ 的程序,此 根据之前的规律,就可以用来提升 JVM 的效率了。方法是,把堆分成几个部分(就是所谓的分代),分别是新生代、老年代,以及永生代。 -![](https://upload-images.jianshu.io/upload_images/1179389-435daa6581893431.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-590c5011-48c4-4543-bd26-6f14c2b8614b.png) 新对象会被分配在新生代内存。一旦新生代内存满了,就会开始对死掉的对象,进行所谓的小型垃圾回收(Minor GC)过程。一片新生代内存里,死掉的越多,回收过程就越快;至于那些还活着的对象,此时就会老化,并最终老到进入老年代内存。 @@ -63,37 +63,37 @@ Major GC 也会触发STW(Stop the World)。通常,Major GC会慢很多, 首先,将任何新对象分配给 eden 空间。 两个 survivor 空间都是空的。 -![](https://upload-images.jianshu.io/upload_images/1179389-85d41f8ee21e3990?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-efe9657b-c7a6-48a8-9037-0e709b1d236c) 当 eden 空间填满时,会触发轻微的垃圾收集。 -![](https://upload-images.jianshu.io/upload_images/1179389-4459380342500664?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-2497947b-92b5-4a7c-9399-1909a3153660) 引用的对象被移动到第一个 survivor 空间。 清除 eden 空间时,将删除未引用的对象。 -![](https://upload-images.jianshu.io/upload_images/1179389-453df479acefff20?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-2b431315-26fa-4ea0-843a-c63ca568f960) 在下一次Minor GC中,Eden区也会做同样的操作。删除未被引用的对象,并将被引用的对象移动到Survivor区。然而,这里,他们被移动到了第二个Survivor区(S1)。 此外,第一个Survivor区(S0)中,在上一次Minor GC幸存的对象,会增加年龄,并被移动到S1中。待所有幸存对象都被移动到S1后,S0和Eden区都会被清空。注意,Survivor区中有了不同年龄的对象。 -![](https://upload-images.jianshu.io/upload_images/1179389-0528ede92cfd3ae8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-e2560f59-9b24-4d16-88db-b6ac4d0b6ffe) 在下一次Minor GC中,会重复同样的操作。不过,这一次Survivor区会交换。被引用的对象移动到S0,。幸存的对象增加年龄。Eden区和S1被清空。 -![](https://upload-images.jianshu.io/upload_images/1179389-e01781f12e2759f7?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-aa9f883a-12db-4c8b-8391-3c289b53d804)  此幻灯片演示了 promotion。 在较小的GC之后,当老化的物体达到一定的年龄阈值(在该示例中为8)时,它们从年轻一代晋升到老一代。 -![](https://upload-images.jianshu.io/upload_images/1179389-2902b81426552307?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-dec96816-2912-4127-aaaa-a4d987123f52) 随着较小的GC持续发生,物体将继续被推广到老一代空间。 -![](https://upload-images.jianshu.io/upload_images/1179389-b8b67001c0b138a7?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-6cb31f8a-2eac-489c-88bd-fc643996ab49) 所以这几乎涵盖了年轻一代的整个过程。 最终,将主要对老一代进行GC,清理并最终压缩该空间。 -![](https://upload-images.jianshu.io/upload_images/1179389-1a7e07eeff15e6e7?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-df98a004-e233-4fb5-a31a-f422033ecfa7) -------- @@ -101,7 +101,7 @@ Major GC 也会触发STW(Stop the World)。通常,Major GC会慢很多, Java 堆(Java Heap)是 JVM 所管理的内存中最大的一块,堆又是垃圾收集器管理的主要区域,这里我们主要分析一下 Java 堆的结构。 -![](https://upload-images.jianshu.io/upload_images/1179389-864ad362ade36520.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/tujie-gc-294701a5-1c50-4112-94a1-96a8bab80e34.png) Java 堆主要分为 2 个区域-年轻代与老年代,其中年轻代又分 Eden 区和 Survivor 区,其中 Survivor 区又分 From 和 To 2 个区。可能这时候大家会有疑问,为什么需要 Survivor 区,为什么 Survivor 还要分 2 个区。 @@ -134,4 +134,4 @@ Survivor 区相当于是 Eden 区和 Old 区的一个缓冲,类似于我们交 ---- -参考链接:https://mp.weixin.qq.com/s/RQGImK3-SrvJfs8eYCiv4A \ No newline at end of file +参考链接:https://mp.weixin.qq.com/s/RQGImK3-SrvJfs8eYCiv4A diff --git a/docs/jvm/zijiema-zhiling.md b/docs/jvm/zijiema-zhiling.md index d0a7737bd91e8094e80f57f8b31392d5cafac99a..9ffeea2a2f9dfcf22c11bc250cb6711f9a180170 100644 --- a/docs/jvm/zijiema-zhiling.md +++ b/docs/jvm/zijiema-zhiling.md @@ -39,7 +39,7 @@ Java 字节码由操作码和操作数组成。 x 为操作码助记符,表明是哪一种数据类型。见下表所示。 -![](https://img-blog.csdnimg.cn/img_convert/cb7b6b29c419c1437c40282cbc8ce4fe.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-879da2f2-fb72-48a9-985e-5a28a9fc8814.png) 像 arraylength 指令,没有操作码助记符,它没有代表数据类型的特殊字符,但操作数只能是一个数组类型的对象。 @@ -55,7 +55,7 @@ private void load(int age, String name, long birthday, boolean sex) { 通过 jclasslib 看一下 `load()` 方法(4 个参数)的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/733a2b75879ba59a36e58911cfe2c45d.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-05bfae95-2a33-402c-9041-570093729c42.png) - iload_1:将局部变量表中下标为 1 的 int 变量压入操作数栈中。 - aload_2:将局部变量表中下标为 2 的引用数据类型变量(此时为 String)压入操作数栈中。 @@ -64,7 +64,7 @@ private void load(int age, String name, long birthday, boolean sex) { 通过查看局部变量表就能关联上了。 -![](https://img-blog.csdnimg.cn/img_convert/4560f520a117f4ba77ae3563079009be.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-79d74946-ce9e-41d4-b889-bda861f847bc.png) **2)将常量池中的常量压入操作数栈中** @@ -73,7 +73,7 @@ private void load(int age, String name, long birthday, boolean sex) { **const 系列**,用于特殊的常量入栈,要入栈的常量隐含在指令本身。 -![](https://img-blog.csdnimg.cn/img_convert/9b7ae2382755aeb504ddad064d8964af.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-270c314d-872b-43b0-861f-417eafc046fd.png) **push 系列**,主要包括 bipush 和 sipush,前者接收 8 位整数作为参数,后者接收 16 位整数。 @@ -101,7 +101,7 @@ public void pushConstLdc() { 通过 jclasslib 看一下 `pushConstLdc()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/b69c0cca77a38f3baba7abac254576a4.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-b34fc802-18bb-46a1-8d24-de2087c9b6bf.png) - iconst_m1:将 -1 入栈。范围 [-1,5]。 - bipush 127:将 127 入栈。范围 [-128,127]。 @@ -136,14 +136,14 @@ public void store(int age, String name) { 通过 jclasslib 看一下 `store()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/c6eb018c14edaee964a8c2e3116291c1.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-d955468c-d07d-47cd-b82b-c03ecea8753d.png) - istore_3:从操作数中弹出一个整数,并把它赋值给局部变量表中索引为 3 的变量。 - astore 4:从操作数中弹出一个引用数据类型,并把它赋值给局部变量表中索引为 4 的变量。 通过查看局部变量表就能关联上了。 -![](https://img-blog.csdnimg.cn/img_convert/bde3547dc74375477315d5dfafcd0e1e.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-a08c20cb-c148-47c9-91e2-df37e68989a9.png) ### 02、算术指令 @@ -200,7 +200,7 @@ public void calculate(int age) { 通过 jclasslib 看一下 `calculate()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/45314e447b9f9fac2ccf873aa00ca5ab.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-598e4204-fd77-425b-b536-1e001cda8e13.png) - iadd,加法 - isub,减法 @@ -238,7 +238,7 @@ public void updown() { 通过 jclasslib 看一下 `updown()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/309c72bbe9c10144b78570ab08797710.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-0c3e47c6-1e25-4926-a838-20cf146a8993.png) - i2d,int 宽化为 double - f2l, float 窄化为 long @@ -269,7 +269,7 @@ public void newObject() { 通过 jclasslib 看一下 `newObject()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/425c6162880081c0ab797a572ff6354a.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-8125da3d-876c-43fe-8347-cb2341408088.png) - `new #13 `,创建一个 String 对象。 @@ -304,7 +304,7 @@ public class Writer { 通过 jclasslib 看一下 `main()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/91746596e52cdd365b93a835aa27e67b.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-70441cfc-7c6e-4a5e-b0dd-818fc3fa1a67.png) - `getstatic #2 `,访问静态变量 mark - `getfield #6 `,访问成员变量 name @@ -428,7 +428,7 @@ invokestatic #11 // Method print:()V 方法返回指令根据方法的返回值类型进行区分,常见的返回指令见下图。 -![](https://img-blog.csdnimg.cn/img_convert/4a465d6c2ae7de70e1a1f12d8a40ac25.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-37513fa2-fdba-45db-adfc-c18225c6ff8b.png) ### 06、操作数栈管理指令 @@ -453,7 +453,7 @@ public class Dup { 通过 jclasslib 看一下 `incAndGet()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/402875d4c69a320984350692132d683d.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-642ca54e-5808-428d-9840-ebf478e95c17.png) - aload_0:将 this 入栈。 - dup:复制栈顶的 this。 @@ -490,13 +490,13 @@ public void lcmp(long a, long b) { 通过 jclasslib 看一下 `lcmp()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/2f46f58d1429d54e6d09e7fcc53d72ce.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-e8fa6685-b3d4-4f42-8fc5-8a4d8a9efe7b.png) lcmp 用于两个 long 型的数据进行比较。 **2)条件跳转指令** -![](https://img-blog.csdnimg.cn/img_convert/909f03d1ae0b08bd64643358706156ac.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-5de34f26-52ad-4e07-a20d-91ea92038984.png) 这些指令都会接收两个字节的操作数,它们的统一含义是,弹出栈顶元素,测试它是否满足某一条件,满足的话,跳转到对应位置。 @@ -519,13 +519,13 @@ public void fi() { 通过 jclasslib 看一下 `fi()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/f35d01d4ae60032f86993f46134f155b.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-d0561d5c-ae21-48e7-9e7c-4aae87d02f56.png) `3 ifne 12 (+9)` 的意思是,如果栈顶的元素不等于 0,跳转到第 12(3+9)行 `12 bipush 20`。 **3)比较条件转指令** -![](https://img-blog.csdnimg.cn/img_convert/84f3fc2310616ffbe9fad460d7f75325.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-bfab6edd-d63f-45a7-8838-997e7630fa2a.png) 前缀“if_”后,以字符“i”开头的指令针对 int 型整数进行操作,以字符“a”开头的指令表示对象的比较。 @@ -541,7 +541,7 @@ public void compare() { 通过 jclasslib 看一下 `compare()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/9f9e9e9a24d7e62622fa5d13be4f316a.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-d4f9a680-1364-4af9-9474-c0763c9bc6f7.png) `11 if_icmple 18 (+7)` 的意思是,如果栈顶的两个 int 类型的数值比较的话,如果前者小于后者时跳转到第 18 行(11+7)。 @@ -571,7 +571,7 @@ public void switchTest(int select) { 通过 jclasslib 看一下 `switchTest()` 方法的字节码指令。 -![](https://img-blog.csdnimg.cn/img_convert/13f65030f2bd0ad8d0c8a631c47fae14.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zijiema-zhiling-04e166ae-13c7-4025-804a-be88e2923a50.png) case 2 的时候没有 break,所以 case 2 和 case 3 是连续的,用的是 tableswitch。如果等于 1,跳转到 28 行;如果等于 2 和 3,跳转到 34 行,如果是 default,跳转到 40 行。 diff --git a/docs/jvm/zongjie.md b/docs/jvm/zongjie.md index 330d5e809e303d6ec498c6f9c95d56a6124fa277..a58c68fd19a546b9e61c0276da0073d325ea9c1a 100644 --- a/docs/jvm/zongjie.md +++ b/docs/jvm/zongjie.md @@ -44,7 +44,7 @@ Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode) # 使用的是H ## 二、Java 内存区域 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/java虚拟机运行时数据区.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-1d779fca-b6a4-4982-b746-2a8db7805645.png) ### 2.1 程序计数器 @@ -88,7 +88,7 @@ Java 堆(Java Heap)是虚拟机所管理的最大一块的内存空间,它 + **指针碰撞**:假设 Java 堆中内存是绝对规整的,所有使用的内存放在一边,所有未被使用的内存放在另外一边,中间以指针作为分界点指示器。此时内存分配只是将指针向空闲方向偏移出对象大小的空间即可,这种方式被称为指针碰撞。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_指针碰撞.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-afb11e2b-f457-4a19-bb21-f659756061ec.png) + **空闲列表**:如果 Java 堆不是规整的,此时虚拟机需要维护一个列表,记录哪些内存块是可用的,哪些是不可用的。在进行内存分配时,只需要从该列表中选取出一块足够的内存空间划分给对象实例即可。 @@ -136,12 +136,12 @@ Java 堆(Java Heap)是虚拟机所管理的最大一块的内存空间,它 通过句柄访问对象: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_通过句柄访问对象.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-f6b5eb22-a5af-40c0-8c80-00fdd6d16b1d.png) 通过直接指针访问对象: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_通过直接指针访问对象.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-f696f4a8-af51-4e28-9d72-c2f6b1e5b3db.png) 句柄访问的优点在于对象移动时(垃圾收集时移动对象是非常普遍的行为)只需要改变句柄中实例数据的指针,而 `reference` 本生并不需要修改;指针访问则反之,由于其 `reference` 中存储的直接就是对象地址,所以当对象移动时, `reference` 需要被修改。但针对只需要访问对象本身的场景,指针访问则可以减少一次定位开销。由于对象访问是一项非常频繁的操作,所以这类减少的效果会非常显著,基于这个原因,HotSpot 主要使用的是指针访问的方式。 @@ -172,7 +172,7 @@ System.gc(); 上面的代码在大多数虚拟机中都能被正确的回收,因为大多数主流的虚拟机都是采用的可达性分析方法来判断对象是否死亡。可达性分析是通过一系列被称为 `GC Roots` 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径被称为引用链(Reference Chain),如果某个对象到 `GC Roots` 间没有任何引用链相连,这代表 `GC Roots` 到该对象不可达, 此时证明此该对象不可能再被使用。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_可达性分析.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-f1325549-5689-4398-a39c-c0a6836f6077.png) 在 Java 语言中,固定可作为 `GC Roots` 的对象包括以下几种: @@ -233,7 +233,7 @@ System.gc(); 它是最基础的垃圾收集算法,收集过程分为两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象;也可以反过来,标记存活对象,统一回收所有未被标记的对象。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_标记清除算法.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-7d489254-f1e0-4feb-bd4a-af129767a787.png) 它主要有以下两个缺点: @@ -248,7 +248,7 @@ System.gc(); + 如果内存中多数对象都是存活的,这种算法将产生大量的复制开销; + 浪费内存空间,内存空间变为了原有的一半。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_标记复制算法.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-f4572b93-f7f3-41cc-9901-93816e79c789.png) 基于新生代 “朝生夕灭” 的特点,大多数虚拟机都不会按照 1:1 的比例来进行内存划分,例如 HotSpot 虚拟机会将内存空间划分为一块较大的 `Eden` 和 两块较小的 `Survivor` 空间,它们之间的比例是 8:1:1 。 每次分配时只会使用 `Eden` 和其中的一块 `Survivor` ,发生垃圾回收时,只需要将存活的对象一次性复制到另外一块 `Survivor` 上,这样只有 10% 的内存空间会被浪费掉。当 `Survivor` 空间不足以容纳一次 `Minor GC` 时,此时由其他内存区域(通常是老年代)来进行分配担保。 @@ -257,7 +257,7 @@ System.gc(); 标记-整理算法是在标记完成后,让所有存活对象都向内存的一端移动,然后直接清理掉边界以外的内存。其优点在于可以避免内存空间碎片化的问题,也可以充分利用内存空间;其缺点在于根据所使用的收集器的不同,在移动存活对象时可能要全程暂停用户程序: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_标记移动算法.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-e674c49f-c55b-4eba-95ea-34be62d55a78.png) ## 五、经典垃圾收集器 @@ -270,7 +270,7 @@ System.gc(); HotSpot 虚拟机中一共存在七款经典的垃圾收集器: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_hotspot_垃圾收集器.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-1fa20f99-d203-42d6-982c-f1bd66a0c929.png) > 注:收集器之间存在连线,则代表它们可以搭配使用。 @@ -278,14 +278,14 @@ HotSpot 虚拟机中一共存在七款经典的垃圾收集器: Serial 收集器是最基础、历史最悠久的收集器,它是一个单线程收集器,在进行垃圾回收时,必须暂停其他所有的工作线程,直到收集结束,这是其主要缺点。它的优点在于单线程避免了多线程复杂的上下文切换,因此在单线程环境下收集效率非常高,由于这个优点,迄今为止,其仍然是 HotSpot 虚拟机在客户端模式下默认的新生代收集器: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_收集器1.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-ec6ec994-6fe4-4d5b-890c-7f31b5a607a0.png) ### 5.2 ParNew 收集器 他是 Serial 收集器的多线程版本,可以使用多条线程进行垃圾回收: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_收集器2.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-ae8c47c7-538b-426a-85e4-d422d1c37683.png) ### 5.3 Parallel Scavenge 收集器 @@ -304,14 +304,14 @@ Parallel Scavenge 收集器提供两个参数用于精确控制吞吐量: 从名字也可以看出来,它是 Serial 收集器的老年代版本,同样是一个单线程收集器,采用 标记-整理 算法,主要用于给客户端模式下的 HotSpot 虚拟机使用: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_收集器1.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-b199ece2-8de2-4f24-b50a-ea0c0d16bd7b.png) ### 5.5 Paralled Old 收集器 Paralled Old 是 Parallel Scavenge 收集器的老年代版本,支持多线程并发收集,采用 标记-整理 算法实现: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_收集器3.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-30dd34d5-27df-4a6f-b391-5a7928dfb3ab.png) ### 5.6 CMS 收集器 @@ -323,7 +323,7 @@ CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时 3. **重新标记 (remark)**:采用增量更新算法,对并发标记阶段因为用户线程运行而产生变动的那部分对象进行重新标记,耗时比初始标记稍长且需要暂停用户线程; 4. **并发清除 (inital sweep)**:并发清除掉已经死亡的对象,耗时长但不需要暂停用户线程。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_收集器4.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-7ad8d755-53f2-422a-9cea-c792b0579d8b.png) 其优点在于耗时长的 并发标记 和 并发清除 阶段都不需要暂停用户线程,因此其停顿时间较短,其主要缺点如下: @@ -336,7 +336,7 @@ CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时 Garbage First(简称 G1)是一款面向服务端的垃圾收集器,也是 JDK 9 服务端模式下默认的垃圾收集器,它的诞生具有里程碑式的意义。G1 虽然也遵循分代收集理论,但不再以固定大小和固定数量来划分分代区域,而是把连续的 Java 堆划分为多个大小相等的独立区域(Region)。每一个 Region 都可以根据不同的需求来扮演新生代的 `Eden` 空间、`Survivor` 空间或者老年代空间,收集器会根据其扮演角色的不同而采用不同的收集策略。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/G1_内存布局.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-e0f5da26-6e46-4f9d-bfcc-0842cc7079e7.png) 上面还有一些 Region 使用 H 进行标注,它代表 Humongous,表示这些 Region 用于存储大对象(humongous object,H-obj),即大小大于等于 region 一半的对象。G1 收集器的运行大致可以分为以下四个步骤: @@ -346,7 +346,7 @@ Garbage First(简称 G1)是一款面向服务端的垃圾收集器,也是 3. **最终标记 (Final Marking)**:对用户线程做一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的少量的 STAB 记录。虽然并发标记阶段会处理 SATB 记录,但由于处理时用户线程依然是运行中的,因此依然会有少量的变动,所以需要最终标记来处理; 4. **筛选回收 (Live Data Counting and Evacuation)**:负责更新 Regin 统计数据,按照各个 Regin 的回收价值和成本进行排序,在根据用户期望的停顿时间进行来指定回收计划,可以选择任意多个 Regin 构成回收集。然后将回收集中 Regin 的存活对象复制到空的 Regin 中,再清理掉整个旧的 Regin 。此时因为涉及到存活对象的移动,所以需要暂停用户线程,并由多个收集线程并行执行。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_收集器5.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-3cf7a78a-d541-49af-929a-4bf8f4f0edd9.png) ### 5.8 内存分配原则 @@ -379,7 +379,7 @@ Java 虚拟机把描述类的数据从 Class 文件加载到内存,并对数 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载、验证、准备、卸载、解析、初始化、使用、卸载七个阶段,其中验证、准备、解析三个部分统称为连接: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_类的生命周期.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-e154964a-9a0a-46de-bf37-75b483956d6c.png) 《Java 虚拟机规范》严格规定了有且只有六种情况必须立即对类进行初始化: @@ -458,7 +458,7 @@ Java 虚拟机把描述类的数据从 Class 文件加载到内存,并对数 JDK 9 之前的 Java 应用都是由这三种类加载器相互配合来完成加载: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_双亲委派模型.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-c1fcdc37-4e5a-4ed3-94b1-ad4afa2dba7c.png) 上图所示的各种类加载器之间的层次关系被称为类加载器的 “双亲委派模型”,“双亲委派模型” 要求除了顶层的启动类加载器外,其余的类加载器都应该有自己的父类加载器,需要注意的是这里的加载器之间的父子关系一般不是以继承关系来实现的,而是使用组合关系来复用父类加载器的代码。 @@ -473,7 +473,7 @@ JDK 9 之后为了适应模块化的发展,类加载器做了如下变化: + 当平台及应用程序类加载器收到类加载请求时,要首先判断该类是否能够归属到某一个系统模块中,如果可以找到这样的归属关系,就要优先委派给负责那个模块的加载器完成加载; + 启动类加载器、平台类加载器、应用程序类加载器全部继承自 `java.internal.loader.BuiltinClassLoader` ,BuiltinClassLoader 中实现了新的模块化架构下类如何从模块中加载的逻辑,以及模块中资源可访问性的处理。 -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/jvm_jdk9_双亲委派模型.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-04b18ddb-3457-4e46-ba53-78237d234e37.png) ## 七、程序编译 @@ -506,7 +506,7 @@ JDK 9 之后为了适应模块化的发展,类加载器做了如下变化: 以上层次并不是固定不变的,根据不同的运行参数和版本,虚拟机可以调整分层的数量。各层次编译之间的交互转换关系如下图所示: -![](https://gitee.com/heibaiying/Full-Stack-Notes/raw/master/pictures/分层编译的交互关系.png) +![](https://cdn.jsdelivr.net/gh/itwanger/toBeBetterJavaer/images/jvm/zongjie-2188c350-fdb8-4fee-b2f0-5311795f386b.png) 实施分层编译后,解释器、客户端编译器和服务端编译器就会同时工作,可以用客户端编译器获取更高的编译速度、用服务端编译器来获取更好的编译质量。 @@ -570,4 +570,4 @@ public static String concat(String... strings) { 对于虚拟机执行子系统来说,每次数组元素的读写都带有一次隐含的上下文检查以避免访问越界。如果数组的访问发生在循环之中,并且使用循环变量来访问数据,即循环变量的取值永远在 [0,list.length) 之间,那么此时就可以消除整个循环的数据边界检查,从而避免多次无用的判断。 -原文链接:https://github.com/heibaiying/Full-Stack-Notes \ No newline at end of file +原文链接:https://github.com/heibaiying/Full-Stack-Notes diff --git a/images/jvm/asm-3c8c8db4-5b6a-4576-b147-62965d0e0c1c.jpg b/images/jvm/asm-3c8c8db4-5b6a-4576-b147-62965d0e0c1c.jpg new file mode 100644 index 0000000000000000000000000000000000000000..29008866c057c2bc3047178b7b0c5c56ade0406c Binary files /dev/null and b/images/jvm/asm-3c8c8db4-5b6a-4576-b147-62965d0e0c1c.jpg differ diff --git a/images/jvm/asm-43844b78-c01f-4990-b038-3c91ff2eeb34.jpg b/images/jvm/asm-43844b78-c01f-4990-b038-3c91ff2eeb34.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9f470d86291d1a9a3a25a45c3b61e96e4f22f97f Binary files /dev/null and b/images/jvm/asm-43844b78-c01f-4990-b038-3c91ff2eeb34.jpg differ diff --git a/images/jvm/asm-4670450e-6199-4562-9cf4-354234c734c8.jpg b/images/jvm/asm-4670450e-6199-4562-9cf4-354234c734c8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1de2210bfb72d242756eabd13f53a87b921bc90 Binary files /dev/null and b/images/jvm/asm-4670450e-6199-4562-9cf4-354234c734c8.jpg differ diff --git a/images/jvm/asm-9808d639-327f-4796-80d4-1809be0b9106.jpg b/images/jvm/asm-9808d639-327f-4796-80d4-1809be0b9106.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b1bf1c9fefe95d1ec0a220034c797e2e47de1797 Binary files /dev/null and b/images/jvm/asm-9808d639-327f-4796-80d4-1809be0b9106.jpg differ diff --git a/images/jvm/asm-e31b7e50-1d48-4eef-9552-6fa7e6c68fed.jpg b/images/jvm/asm-e31b7e50-1d48-4eef-9552-6fa7e6c68fed.jpg new file mode 100644 index 0000000000000000000000000000000000000000..efb487a7c4c6b4a74c2bae913723ca4dac1bf5aa Binary files /dev/null and b/images/jvm/asm-e31b7e50-1d48-4eef-9552-6fa7e6c68fed.jpg differ diff --git a/images/jvm/bytecode-5f328e11-3486-4eb4-8fa9-5c5febfab894.png b/images/jvm/bytecode-5f328e11-3486-4eb4-8fa9-5c5febfab894.png new file mode 100644 index 0000000000000000000000000000000000000000..f48c6100a998746640e82f1e7a6e1ee3127def0f Binary files /dev/null and b/images/jvm/bytecode-5f328e11-3486-4eb4-8fa9-5c5febfab894.png differ diff --git a/images/jvm/bytecode-84b7af5c-93b1-4f63-bb30-946ab3d7e98c.png b/images/jvm/bytecode-84b7af5c-93b1-4f63-bb30-946ab3d7e98c.png new file mode 100644 index 0000000000000000000000000000000000000000..617024469fc3c842a924e74999faddc43c67a5f6 Binary files /dev/null and b/images/jvm/bytecode-84b7af5c-93b1-4f63-bb30-946ab3d7e98c.png differ diff --git a/images/jvm/bytecode-bd941085-ff0e-4abf-a5f9-afb0493bfed7.png b/images/jvm/bytecode-bd941085-ff0e-4abf-a5f9-afb0493bfed7.png new file mode 100644 index 0000000000000000000000000000000000000000..b478801020fb8113065fdff501ebab14d3e6f06c Binary files /dev/null and b/images/jvm/bytecode-bd941085-ff0e-4abf-a5f9-afb0493bfed7.png differ diff --git a/images/jvm/bytecode-cbf16ce9-7853-4050-a1c0-8b874f3b0c1e.png b/images/jvm/bytecode-cbf16ce9-7853-4050-a1c0-8b874f3b0c1e.png new file mode 100644 index 0000000000000000000000000000000000000000..3c5c90ac5621b5032b98d46049f792c5113289df Binary files /dev/null and b/images/jvm/bytecode-cbf16ce9-7853-4050-a1c0-8b874f3b0c1e.png differ diff --git a/images/jvm/bytecode-d12d6983-f427-40d2-bb4b-3a2c6c4c7806.png b/images/jvm/bytecode-d12d6983-f427-40d2-bb4b-3a2c6c4c7806.png new file mode 100644 index 0000000000000000000000000000000000000000..1d5f028c90cb1bb9e9ddbc09fd11ea5051397cc6 Binary files /dev/null and b/images/jvm/bytecode-d12d6983-f427-40d2-bb4b-3a2c6c4c7806.png differ diff --git a/images/jvm/bytecode-dd31bbd6-c75c-4426-9437-c0f57ea3b86f.png b/images/jvm/bytecode-dd31bbd6-c75c-4426-9437-c0f57ea3b86f.png new file mode 100644 index 0000000000000000000000000000000000000000..4f060ce8c74d07a627ce096ee3e286ddca76e719 Binary files /dev/null and b/images/jvm/bytecode-dd31bbd6-c75c-4426-9437-c0f57ea3b86f.png differ diff --git a/images/jvm/bytecode-fd434d5c-ffc6-4a24-9787-98e573035068.png b/images/jvm/bytecode-fd434d5c-ffc6-4a24-9787-98e573035068.png new file mode 100644 index 0000000000000000000000000000000000000000..94c31fe7fa7dc94cb18fe5f2c3b87f22edbb79ad Binary files /dev/null and b/images/jvm/bytecode-fd434d5c-ffc6-4a24-9787-98e573035068.png differ diff --git a/images/jvm/class-load-01.png b/images/jvm/class-load-01.png new file mode 100644 index 0000000000000000000000000000000000000000..cb703f90c84e7e48c1789c67146bc74bb666d624 Binary files /dev/null and b/images/jvm/class-load-01.png differ diff --git a/images/jvm/class-load-02.png b/images/jvm/class-load-02.png new file mode 100644 index 0000000000000000000000000000000000000000..8c29e42dabf6b8e0659ba134441896e31b9649be Binary files /dev/null and b/images/jvm/class-load-02.png differ diff --git a/images/jvm/compile-jdk-129ede68-c368-461e-92d6-38a8e5dee344.png b/images/jvm/compile-jdk-129ede68-c368-461e-92d6-38a8e5dee344.png new file mode 100644 index 0000000000000000000000000000000000000000..357d66cd8210d15c1ff6d192203f241cfdd5f36a Binary files /dev/null and b/images/jvm/compile-jdk-129ede68-c368-461e-92d6-38a8e5dee344.png differ diff --git a/images/jvm/compile-jdk-1bbbb1f8-da01-46e1-a793-487a25193c68.png b/images/jvm/compile-jdk-1bbbb1f8-da01-46e1-a793-487a25193c68.png new file mode 100644 index 0000000000000000000000000000000000000000..66da406eec20054489662f529c58a1431338f05f Binary files /dev/null and b/images/jvm/compile-jdk-1bbbb1f8-da01-46e1-a793-487a25193c68.png differ diff --git a/images/jvm/compile-jdk-1c781d34-776e-4acc-8d2b-b34bc59fda61.png b/images/jvm/compile-jdk-1c781d34-776e-4acc-8d2b-b34bc59fda61.png new file mode 100644 index 0000000000000000000000000000000000000000..bfa817e94d52e221117cef9ff2e989d04dcc14fc Binary files /dev/null and b/images/jvm/compile-jdk-1c781d34-776e-4acc-8d2b-b34bc59fda61.png differ diff --git a/images/jvm/compile-jdk-27593edc-03e2-4a42-baf3-ed5e5096b3cb.png b/images/jvm/compile-jdk-27593edc-03e2-4a42-baf3-ed5e5096b3cb.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a31d253b4c48e64a093c2274cd6775ab5526e2 Binary files /dev/null and b/images/jvm/compile-jdk-27593edc-03e2-4a42-baf3-ed5e5096b3cb.png differ diff --git a/images/jvm/compile-jdk-2957399f-6451-46dc-a003-76e5159265e9.png b/images/jvm/compile-jdk-2957399f-6451-46dc-a003-76e5159265e9.png new file mode 100644 index 0000000000000000000000000000000000000000..16e48c6a1365fc35c47a4d53402b740d9818fc6d Binary files /dev/null and b/images/jvm/compile-jdk-2957399f-6451-46dc-a003-76e5159265e9.png differ diff --git a/images/jvm/compile-jdk-2a46b215-04e5-458a-b475-4dc31d7fe326.png b/images/jvm/compile-jdk-2a46b215-04e5-458a-b475-4dc31d7fe326.png new file mode 100644 index 0000000000000000000000000000000000000000..46a6803c4453907b2f44d0743bc9da762f6f3b35 Binary files /dev/null and b/images/jvm/compile-jdk-2a46b215-04e5-458a-b475-4dc31d7fe326.png differ diff --git a/images/jvm/compile-jdk-2cf54b29-9b7e-46b2-8cde-4c36960aa09b.png b/images/jvm/compile-jdk-2cf54b29-9b7e-46b2-8cde-4c36960aa09b.png new file mode 100644 index 0000000000000000000000000000000000000000..9090976287bdf6ae276d32b0473f6d0764352f14 Binary files /dev/null and b/images/jvm/compile-jdk-2cf54b29-9b7e-46b2-8cde-4c36960aa09b.png differ diff --git a/images/jvm/compile-jdk-3164cf31-8078-46d7-bee0-22e05b0c08de.png b/images/jvm/compile-jdk-3164cf31-8078-46d7-bee0-22e05b0c08de.png new file mode 100644 index 0000000000000000000000000000000000000000..40a37cd1a6ac31e880339941f03e024c5bb79d50 Binary files /dev/null and b/images/jvm/compile-jdk-3164cf31-8078-46d7-bee0-22e05b0c08de.png differ diff --git a/images/jvm/compile-jdk-33dc0de6-2690-4ba2-9fe7-0e450c44c07b.png b/images/jvm/compile-jdk-33dc0de6-2690-4ba2-9fe7-0e450c44c07b.png new file mode 100644 index 0000000000000000000000000000000000000000..16db5d94b12367c976c515a0622b2e889322998f Binary files /dev/null and b/images/jvm/compile-jdk-33dc0de6-2690-4ba2-9fe7-0e450c44c07b.png differ diff --git a/images/jvm/compile-jdk-3b66d5b6-272f-47bd-88f7-47146a06ef06.png b/images/jvm/compile-jdk-3b66d5b6-272f-47bd-88f7-47146a06ef06.png new file mode 100644 index 0000000000000000000000000000000000000000..f3cae1cf63b237259533c2b803251ff677828b61 Binary files /dev/null and b/images/jvm/compile-jdk-3b66d5b6-272f-47bd-88f7-47146a06ef06.png differ diff --git a/images/jvm/compile-jdk-4e96858f-f681-4498-b1c4-282d317a6a32.png b/images/jvm/compile-jdk-4e96858f-f681-4498-b1c4-282d317a6a32.png new file mode 100644 index 0000000000000000000000000000000000000000..84555ea6042daa71701adc7aae0c24d7ae2fea5d Binary files /dev/null and b/images/jvm/compile-jdk-4e96858f-f681-4498-b1c4-282d317a6a32.png differ diff --git a/images/jvm/compile-jdk-7b7f147e-58c9-4eb5-b407-b8984cd72e1d.png b/images/jvm/compile-jdk-7b7f147e-58c9-4eb5-b407-b8984cd72e1d.png new file mode 100644 index 0000000000000000000000000000000000000000..f017208393a56026c35c77d418f3ad79f4b8d74c Binary files /dev/null and b/images/jvm/compile-jdk-7b7f147e-58c9-4eb5-b407-b8984cd72e1d.png differ diff --git a/images/jvm/compile-jdk-8526d944-a36e-4d37-93a0-9ad4ad53f927.png b/images/jvm/compile-jdk-8526d944-a36e-4d37-93a0-9ad4ad53f927.png new file mode 100644 index 0000000000000000000000000000000000000000..e623e6e7caeb79653dc4c4f8a518511acd5f7d31 Binary files /dev/null and b/images/jvm/compile-jdk-8526d944-a36e-4d37-93a0-9ad4ad53f927.png differ diff --git a/images/jvm/compile-jdk-89020f5a-0909-4c57-8c88-f655293a42a4.png b/images/jvm/compile-jdk-89020f5a-0909-4c57-8c88-f655293a42a4.png new file mode 100644 index 0000000000000000000000000000000000000000..8818e62442ce6d8bfb504e820685c78699dfb3f5 Binary files /dev/null and b/images/jvm/compile-jdk-89020f5a-0909-4c57-8c88-f655293a42a4.png differ diff --git a/images/jvm/compile-jdk-993fac94-2473-4f3b-9737-959510d2fe98.png b/images/jvm/compile-jdk-993fac94-2473-4f3b-9737-959510d2fe98.png new file mode 100644 index 0000000000000000000000000000000000000000..9f373b874d61a3ec106a413569510392e5b45de5 Binary files /dev/null and b/images/jvm/compile-jdk-993fac94-2473-4f3b-9737-959510d2fe98.png differ diff --git a/images/jvm/compile-jdk-a6f6e416-639e-4706-8b40-6152eb3cf85d.png b/images/jvm/compile-jdk-a6f6e416-639e-4706-8b40-6152eb3cf85d.png new file mode 100644 index 0000000000000000000000000000000000000000..a262afe4615d4c998189acb5b2a457c950a4e3c6 Binary files /dev/null and b/images/jvm/compile-jdk-a6f6e416-639e-4706-8b40-6152eb3cf85d.png differ diff --git a/images/jvm/compile-jdk-a86933af-f6d5-4d45-b4ca-33069a212c52.png b/images/jvm/compile-jdk-a86933af-f6d5-4d45-b4ca-33069a212c52.png new file mode 100644 index 0000000000000000000000000000000000000000..43937ce51347e665aa2cc51c3a84123a450c19be Binary files /dev/null and b/images/jvm/compile-jdk-a86933af-f6d5-4d45-b4ca-33069a212c52.png differ diff --git a/images/jvm/compile-jdk-ad0ca5a3-36c7-477d-bd58-d6731a87d762.png b/images/jvm/compile-jdk-ad0ca5a3-36c7-477d-bd58-d6731a87d762.png new file mode 100644 index 0000000000000000000000000000000000000000..bebd3f7488db73ea110227625a1a4f6f515f4c20 Binary files /dev/null and b/images/jvm/compile-jdk-ad0ca5a3-36c7-477d-bd58-d6731a87d762.png differ diff --git a/images/jvm/compile-jdk-ad8023d0-fbb7-48b1-856e-a8818677a0a5.png b/images/jvm/compile-jdk-ad8023d0-fbb7-48b1-856e-a8818677a0a5.png new file mode 100644 index 0000000000000000000000000000000000000000..e06612a0ffbefb2e4bcddb11212950cd6f6560d2 Binary files /dev/null and b/images/jvm/compile-jdk-ad8023d0-fbb7-48b1-856e-a8818677a0a5.png differ diff --git a/images/jvm/compile-jdk-b8d87f09-6178-44c7-9572-a2852e81318d.png b/images/jvm/compile-jdk-b8d87f09-6178-44c7-9572-a2852e81318d.png new file mode 100644 index 0000000000000000000000000000000000000000..4570d503facbd505bab7a426f822480722944e31 Binary files /dev/null and b/images/jvm/compile-jdk-b8d87f09-6178-44c7-9572-a2852e81318d.png differ diff --git a/images/jvm/compile-jdk-c406b2a2-208a-4a54-a869-b3f526e93ccd.png b/images/jvm/compile-jdk-c406b2a2-208a-4a54-a869-b3f526e93ccd.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6399bba5108f7672992cc8ea15c709e595dc75 Binary files /dev/null and b/images/jvm/compile-jdk-c406b2a2-208a-4a54-a869-b3f526e93ccd.png differ diff --git a/images/jvm/compile-jdk-c8117faf-d027-48d3-869b-32d0e98e8372.png b/images/jvm/compile-jdk-c8117faf-d027-48d3-869b-32d0e98e8372.png new file mode 100644 index 0000000000000000000000000000000000000000..c77ba862b38ba1154b814a0516682e91a8c5cbdb Binary files /dev/null and b/images/jvm/compile-jdk-c8117faf-d027-48d3-869b-32d0e98e8372.png differ diff --git a/images/jvm/compile-jdk-cd8a19ba-e9f5-4a4a-a23c-17688f0f459d.png b/images/jvm/compile-jdk-cd8a19ba-e9f5-4a4a-a23c-17688f0f459d.png new file mode 100644 index 0000000000000000000000000000000000000000..33269e29cda52b2fd7c0ac495e5a718680393f25 Binary files /dev/null and b/images/jvm/compile-jdk-cd8a19ba-e9f5-4a4a-a23c-17688f0f459d.png differ diff --git a/images/jvm/compile-jdk-d6a44833-b908-4824-8862-1679bfdddfa3.png b/images/jvm/compile-jdk-d6a44833-b908-4824-8862-1679bfdddfa3.png new file mode 100644 index 0000000000000000000000000000000000000000..9e7011c8bcdb1e3e76ea1d99ec03b6f9e63aa33f Binary files /dev/null and b/images/jvm/compile-jdk-d6a44833-b908-4824-8862-1679bfdddfa3.png differ diff --git a/images/jvm/compile-jdk-f02dff40-f27e-476c-998b-bd6cdb5d3559.png b/images/jvm/compile-jdk-f02dff40-f27e-476c-998b-bd6cdb5d3559.png new file mode 100644 index 0000000000000000000000000000000000000000..a770deecf0a9962bed979cccc7913f5e4cc56be7 Binary files /dev/null and b/images/jvm/compile-jdk-f02dff40-f27e-476c-998b-bd6cdb5d3559.png differ diff --git a/images/jvm/compile-jdk-f9b55425-f308-44e8-8812-ac59b2707c81.png b/images/jvm/compile-jdk-f9b55425-f308-44e8-8812-ac59b2707c81.png new file mode 100644 index 0000000000000000000000000000000000000000..d170ba914dbf0da2e1455adbf079870d704df1a7 Binary files /dev/null and b/images/jvm/compile-jdk-f9b55425-f308-44e8-8812-ac59b2707c81.png differ diff --git a/images/jvm/compile-jdk-fd3cf88d-007e-4615-99b5-a3499c35ef40.png b/images/jvm/compile-jdk-fd3cf88d-007e-4615-99b5-a3499c35ef40.png new file mode 100644 index 0000000000000000000000000000000000000000..f50a8afec3f42f9dcc72b830b04362c05684fe3b Binary files /dev/null and b/images/jvm/compile-jdk-fd3cf88d-007e-4615-99b5-a3499c35ef40.png differ diff --git a/images/jvm/compile-jdk-ffa10d36-3a77-48aa-ae0c-d3daf67f9a19.png b/images/jvm/compile-jdk-ffa10d36-3a77-48aa-ae0c-d3daf67f9a19.png new file mode 100644 index 0000000000000000000000000000000000000000..b2cfabf8e94af2cf9344a4c6b9666771a0d1ac92 Binary files /dev/null and b/images/jvm/compile-jdk-ffa10d36-3a77-48aa-ae0c-d3daf67f9a19.png differ diff --git a/images/jvm/gc-1636ce77-77b3-4b10-b75a-c0c2d28912c5.jpg b/images/jvm/gc-1636ce77-77b3-4b10-b75a-c0c2d28912c5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b71d6b74579f37c8796068f117861bdfb35d896a Binary files /dev/null and b/images/jvm/gc-1636ce77-77b3-4b10-b75a-c0c2d28912c5.jpg differ diff --git a/images/jvm/gc-2001e224-0f34-4429-bc89-a8fbe8ab271c.jpg b/images/jvm/gc-2001e224-0f34-4429-bc89-a8fbe8ab271c.jpg new file mode 100644 index 0000000000000000000000000000000000000000..422facfe97eb3c9777d813488a2698636454eb55 Binary files /dev/null and b/images/jvm/gc-2001e224-0f34-4429-bc89-a8fbe8ab271c.jpg differ diff --git a/images/jvm/gc-2d47a225-ad9d-4f15-9b4d-7dce9a693adf.jpg b/images/jvm/gc-2d47a225-ad9d-4f15-9b4d-7dce9a693adf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..55e308e1fa6626fdbc1aea86745768c01f9f9113 Binary files /dev/null and b/images/jvm/gc-2d47a225-ad9d-4f15-9b4d-7dce9a693adf.jpg differ diff --git a/images/jvm/gc-59dddea1-b6bc-4fd4-bb79-d81adbdc7bed.jpg b/images/jvm/gc-59dddea1-b6bc-4fd4-bb79-d81adbdc7bed.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a1901b2495d27b91e01edd774a1994542c37493 Binary files /dev/null and b/images/jvm/gc-59dddea1-b6bc-4fd4-bb79-d81adbdc7bed.jpg differ diff --git a/images/jvm/gc-691109d2-bee4-4a79-8da6-87c5fd233f54.jpg b/images/jvm/gc-691109d2-bee4-4a79-8da6-87c5fd233f54.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fb2b85ec98f476e16e0879dbb1ee136ae2e3c30c Binary files /dev/null and b/images/jvm/gc-691109d2-bee4-4a79-8da6-87c5fd233f54.jpg differ diff --git a/images/jvm/gc-6abf9f50-dc53-4e8f-a7f6-3e74df8803d6.jpg b/images/jvm/gc-6abf9f50-dc53-4e8f-a7f6-3e74df8803d6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ceade20cd1f0649bfb8e2711e1594f8f4f729514 Binary files /dev/null and b/images/jvm/gc-6abf9f50-dc53-4e8f-a7f6-3e74df8803d6.jpg differ diff --git a/images/jvm/gc-74865618-4576-4f8b-baf3-17d6a71125b9.jpg b/images/jvm/gc-74865618-4576-4f8b-baf3-17d6a71125b9.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f016e930472844f058c6de6ac95c798e7aa98bd4 Binary files /dev/null and b/images/jvm/gc-74865618-4576-4f8b-baf3-17d6a71125b9.jpg differ diff --git a/images/jvm/gc-a138a4b4-56cb-4d6f-a65a-7f4259977476.jpg b/images/jvm/gc-a138a4b4-56cb-4d6f-a65a-7f4259977476.jpg new file mode 100644 index 0000000000000000000000000000000000000000..29d8ae218c23b7a82ba5add066891a4d3e3ec384 Binary files /dev/null and b/images/jvm/gc-a138a4b4-56cb-4d6f-a65a-7f4259977476.jpg differ diff --git a/images/jvm/gc-a2b15e6f-6921-4710-bf76-77858df38c27.jpg b/images/jvm/gc-a2b15e6f-6921-4710-bf76-77858df38c27.jpg new file mode 100644 index 0000000000000000000000000000000000000000..93f2e6de8257d208209d27dd1eafd8f98ced6584 Binary files /dev/null and b/images/jvm/gc-a2b15e6f-6921-4710-bf76-77858df38c27.jpg differ diff --git a/images/jvm/gc-fe980c00-3605-4b5d-a711-7edbfd2c80b0.jpg b/images/jvm/gc-fe980c00-3605-4b5d-a711-7edbfd2c80b0.jpg new file mode 100644 index 0000000000000000000000000000000000000000..26768f9b71ea08a01d8fdbb44852fc105a499847 Binary files /dev/null and b/images/jvm/gc-fe980c00-3605-4b5d-a711-7edbfd2c80b0.jpg differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-3c8a0865-2a77-464e-8dd6-5616fd6a72d7.png b/images/jvm/how-jvm-run-zijiema-zhiling-3c8a0865-2a77-464e-8dd6-5616fd6a72d7.png new file mode 100644 index 0000000000000000000000000000000000000000..b768170e10f495a43e5810a7ce00a8927fdb5705 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-3c8a0865-2a77-464e-8dd6-5616fd6a72d7.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-3ffdbe03-c0e4-49de-97a6-76666964a087.png b/images/jvm/how-jvm-run-zijiema-zhiling-3ffdbe03-c0e4-49de-97a6-76666964a087.png new file mode 100644 index 0000000000000000000000000000000000000000..d70c3944cf6d6cdd698aab1a646d90f4386323b7 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-3ffdbe03-c0e4-49de-97a6-76666964a087.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-49e3f396-7ea8-49f5-81d4-093b9bdfa453.png b/images/jvm/how-jvm-run-zijiema-zhiling-49e3f396-7ea8-49f5-81d4-093b9bdfa453.png new file mode 100644 index 0000000000000000000000000000000000000000..af65126acd922d78d32ae6509ce4ac1885e4e633 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-49e3f396-7ea8-49f5-81d4-093b9bdfa453.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-630b50e3-fc37-4748-8d20-852d5358f87a.png b/images/jvm/how-jvm-run-zijiema-zhiling-630b50e3-fc37-4748-8d20-852d5358f87a.png new file mode 100644 index 0000000000000000000000000000000000000000..9a4b65f2adcdc049c7408dca5f9059f9b144c264 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-630b50e3-fc37-4748-8d20-852d5358f87a.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-6734774b-376c-49bf-a915-508c7e829557.png b/images/jvm/how-jvm-run-zijiema-zhiling-6734774b-376c-49bf-a915-508c7e829557.png new file mode 100644 index 0000000000000000000000000000000000000000..d50a1c2c778d17a1ca84b8fd86403a3c6818f2d6 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-6734774b-376c-49bf-a915-508c7e829557.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-70ab6bf6-4fbb-4722-99b4-a93d5061630c.png b/images/jvm/how-jvm-run-zijiema-zhiling-70ab6bf6-4fbb-4722-99b4-a93d5061630c.png new file mode 100644 index 0000000000000000000000000000000000000000..8c3bddde2947b00c6741878378f6d3f2d60012a6 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-70ab6bf6-4fbb-4722-99b4-a93d5061630c.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-91ad04f8-1620-44c9-83d1-6fbd7860701a.png b/images/jvm/how-jvm-run-zijiema-zhiling-91ad04f8-1620-44c9-83d1-6fbd7860701a.png new file mode 100644 index 0000000000000000000000000000000000000000..c0dbd95750ace93f299a18e5fca5f46e7976ed57 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-91ad04f8-1620-44c9-83d1-6fbd7860701a.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-93a21aaf-ff67-445d-8ddb-ac6f72fd9b25.png b/images/jvm/how-jvm-run-zijiema-zhiling-93a21aaf-ff67-445d-8ddb-ac6f72fd9b25.png new file mode 100644 index 0000000000000000000000000000000000000000..a1e559c94227b0d9cf014534fcbf132fb86aaebb Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-93a21aaf-ff67-445d-8ddb-ac6f72fd9b25.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-a58ee82e-c0b0-4c06-9606-f7a0f0df0de9 b/images/jvm/how-jvm-run-zijiema-zhiling-a58ee82e-c0b0-4c06-9606-f7a0f0df0de9 new file mode 100644 index 0000000000000000000000000000000000000000..7490e4ddf8e1a60d867100f72f61eece18d2bb0d Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-a58ee82e-c0b0-4c06-9606-f7a0f0df0de9 differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-c37add5c-a74b-4bd6-8c8e-9085d9e6d374.png b/images/jvm/how-jvm-run-zijiema-zhiling-c37add5c-a74b-4bd6-8c8e-9085d9e6d374.png new file mode 100644 index 0000000000000000000000000000000000000000..38ec34da17b40f6caedd54745a485f63f2778528 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-c37add5c-a74b-4bd6-8c8e-9085d9e6d374.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-e5e6037c-9be1-472f-8ab3-2754466e7828.png b/images/jvm/how-jvm-run-zijiema-zhiling-e5e6037c-9be1-472f-8ab3-2754466e7828.png new file mode 100644 index 0000000000000000000000000000000000000000..4573c1151b0dbf67591edb91752bb8d6f420be47 Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-e5e6037c-9be1-472f-8ab3-2754466e7828.png differ diff --git a/images/jvm/how-jvm-run-zijiema-zhiling-f790aa0f-d742-465b-91bf-5f143ee098c1.png b/images/jvm/how-jvm-run-zijiema-zhiling-f790aa0f-d742-465b-91bf-5f143ee098c1.png new file mode 100644 index 0000000000000000000000000000000000000000..fbdd44b75f16aadee7ca6da843a54e62ad7bd46b Binary files /dev/null and b/images/jvm/how-jvm-run-zijiema-zhiling-f790aa0f-d742-465b-91bf-5f143ee098c1.png differ diff --git a/images/jvm/hsdb-026fb881-59a2-4e0f-ac4a-a2a7b505a707.png b/images/jvm/hsdb-026fb881-59a2-4e0f-ac4a-a2a7b505a707.png new file mode 100644 index 0000000000000000000000000000000000000000..26ae997dbdfc3e6f34d02cfd0ebe54ca9c5a2ce5 Binary files /dev/null and b/images/jvm/hsdb-026fb881-59a2-4e0f-ac4a-a2a7b505a707.png differ diff --git a/images/jvm/hsdb-07d80d18-be4e-4861-bea3-291eea0ff262.png b/images/jvm/hsdb-07d80d18-be4e-4861-bea3-291eea0ff262.png new file mode 100644 index 0000000000000000000000000000000000000000..a94087e72f92e994e5be7a2d9672e3a038d4ab4d Binary files /dev/null and b/images/jvm/hsdb-07d80d18-be4e-4861-bea3-291eea0ff262.png differ diff --git a/images/jvm/hsdb-25fa5e06-0250-424b-8b05-aea770e80963.png b/images/jvm/hsdb-25fa5e06-0250-424b-8b05-aea770e80963.png new file mode 100644 index 0000000000000000000000000000000000000000..e167571d6b9c7b6730bef38f3f25b87caca5d7ca Binary files /dev/null and b/images/jvm/hsdb-25fa5e06-0250-424b-8b05-aea770e80963.png differ diff --git a/images/jvm/hsdb-301ebfc3-c2c4-49de-946a-5d2f1660e669.png b/images/jvm/hsdb-301ebfc3-c2c4-49de-946a-5d2f1660e669.png new file mode 100644 index 0000000000000000000000000000000000000000..3a1e7c65a343aa9c6df1d6d9433cf8e3b84f4ff4 Binary files /dev/null and b/images/jvm/hsdb-301ebfc3-c2c4-49de-946a-5d2f1660e669.png differ diff --git a/images/jvm/hsdb-3baabaf0-1681-4443-b8db-ae08128744d6.png b/images/jvm/hsdb-3baabaf0-1681-4443-b8db-ae08128744d6.png new file mode 100644 index 0000000000000000000000000000000000000000..6fa5145336f048427d34e6b1aa1cb7972996a017 Binary files /dev/null and b/images/jvm/hsdb-3baabaf0-1681-4443-b8db-ae08128744d6.png differ diff --git a/images/jvm/hsdb-47a42bfa-7645-4c9b-bcd8-aeabea1ae44f.png b/images/jvm/hsdb-47a42bfa-7645-4c9b-bcd8-aeabea1ae44f.png new file mode 100644 index 0000000000000000000000000000000000000000..3cf3e7b7285290dc2c3ad05a6b29c0a78bc16a50 Binary files /dev/null and b/images/jvm/hsdb-47a42bfa-7645-4c9b-bcd8-aeabea1ae44f.png differ diff --git a/images/jvm/hsdb-51cb7321-fb7a-42b0-9321-edd410e3d328.png b/images/jvm/hsdb-51cb7321-fb7a-42b0-9321-edd410e3d328.png new file mode 100644 index 0000000000000000000000000000000000000000..b754e0f105456faa6754246383a6381ee32b2eb8 Binary files /dev/null and b/images/jvm/hsdb-51cb7321-fb7a-42b0-9321-edd410e3d328.png differ diff --git a/images/jvm/hsdb-51fb09f4-06d7-4518-8038-5dd69d765862.png b/images/jvm/hsdb-51fb09f4-06d7-4518-8038-5dd69d765862.png new file mode 100644 index 0000000000000000000000000000000000000000..821f461d14d17f0968b7de128284455519376405 Binary files /dev/null and b/images/jvm/hsdb-51fb09f4-06d7-4518-8038-5dd69d765862.png differ diff --git a/images/jvm/hsdb-59231922-9ce3-4107-ab1a-b33818cbab96.png b/images/jvm/hsdb-59231922-9ce3-4107-ab1a-b33818cbab96.png new file mode 100644 index 0000000000000000000000000000000000000000..b7de98b258c37372d6cedcd23c8275908a00e03d Binary files /dev/null and b/images/jvm/hsdb-59231922-9ce3-4107-ab1a-b33818cbab96.png differ diff --git a/images/jvm/hsdb-76084b8d-6134-4866-8891-c24a43a3b836.png b/images/jvm/hsdb-76084b8d-6134-4866-8891-c24a43a3b836.png new file mode 100644 index 0000000000000000000000000000000000000000..81740a325695632767db83529b204269f6444353 Binary files /dev/null and b/images/jvm/hsdb-76084b8d-6134-4866-8891-c24a43a3b836.png differ diff --git a/images/jvm/hsdb-7e4ebd1f-ba9c-4862-b4c3-574de5c30d6b.png b/images/jvm/hsdb-7e4ebd1f-ba9c-4862-b4c3-574de5c30d6b.png new file mode 100644 index 0000000000000000000000000000000000000000..a0b218a978885a852b5c4a4c694002c7192cb8ba Binary files /dev/null and b/images/jvm/hsdb-7e4ebd1f-ba9c-4862-b4c3-574de5c30d6b.png differ diff --git a/images/jvm/hsdb-801d35f2-0c8a-4699-afbf-057c1e6cac6c.png b/images/jvm/hsdb-801d35f2-0c8a-4699-afbf-057c1e6cac6c.png new file mode 100644 index 0000000000000000000000000000000000000000..1f56d5ef7fd484dc94a029d96e0f24d82f9738cc Binary files /dev/null and b/images/jvm/hsdb-801d35f2-0c8a-4699-afbf-057c1e6cac6c.png differ diff --git a/images/jvm/hsdb-85253e10-d0c2-442b-a26b-91b1b2588f1c.png b/images/jvm/hsdb-85253e10-d0c2-442b-a26b-91b1b2588f1c.png new file mode 100644 index 0000000000000000000000000000000000000000..64f8e71ab253be016087cb648d0403f4f7d44649 Binary files /dev/null and b/images/jvm/hsdb-85253e10-d0c2-442b-a26b-91b1b2588f1c.png differ diff --git a/images/jvm/hsdb-85c6fca7-2d1f-4194-bc07-fd1e2ab18632.png b/images/jvm/hsdb-85c6fca7-2d1f-4194-bc07-fd1e2ab18632.png new file mode 100644 index 0000000000000000000000000000000000000000..295fe4ca548f7575b32665c0d696c5c276410e0d Binary files /dev/null and b/images/jvm/hsdb-85c6fca7-2d1f-4194-bc07-fd1e2ab18632.png differ diff --git a/images/jvm/hsdb-88e8c10d-e09c-4a74-95e6-e5b21577459f.png b/images/jvm/hsdb-88e8c10d-e09c-4a74-95e6-e5b21577459f.png new file mode 100644 index 0000000000000000000000000000000000000000..7d587f6ace24c42f9ec08bee8c6b9174b1f50094 Binary files /dev/null and b/images/jvm/hsdb-88e8c10d-e09c-4a74-95e6-e5b21577459f.png differ diff --git a/images/jvm/hsdb-974d211c-e627-40d6-af13-9560ebae0bfa.png b/images/jvm/hsdb-974d211c-e627-40d6-af13-9560ebae0bfa.png new file mode 100644 index 0000000000000000000000000000000000000000..183c24c29f5abab9c1627b1b0eef1fa7da692aab Binary files /dev/null and b/images/jvm/hsdb-974d211c-e627-40d6-af13-9560ebae0bfa.png differ diff --git a/images/jvm/hsdb-a606c6ac-1cfc-44c3-8fdf-e0eeeabbf05a.png b/images/jvm/hsdb-a606c6ac-1cfc-44c3-8fdf-e0eeeabbf05a.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5cba42770fb798abd3f853f9c359ac748db74a Binary files /dev/null and b/images/jvm/hsdb-a606c6ac-1cfc-44c3-8fdf-e0eeeabbf05a.png differ diff --git a/images/jvm/hsdb-b5631e70-be3a-48de-99be-4468632d23e0.png b/images/jvm/hsdb-b5631e70-be3a-48de-99be-4468632d23e0.png new file mode 100644 index 0000000000000000000000000000000000000000..068d0a863437733c9408f8d6fae6c9f8241cbb01 Binary files /dev/null and b/images/jvm/hsdb-b5631e70-be3a-48de-99be-4468632d23e0.png differ diff --git a/images/jvm/hsdb-b7b0ebed-cd38-42b7-bebc-41090409a1db.png b/images/jvm/hsdb-b7b0ebed-cd38-42b7-bebc-41090409a1db.png new file mode 100644 index 0000000000000000000000000000000000000000..11d1dcc0bd6063bb1d56269e85b0c3dba565c1aa Binary files /dev/null and b/images/jvm/hsdb-b7b0ebed-cd38-42b7-bebc-41090409a1db.png differ diff --git a/images/jvm/hsdb-ca5d06a0-1690-4a8f-98cb-aa6bd7800afe.png b/images/jvm/hsdb-ca5d06a0-1690-4a8f-98cb-aa6bd7800afe.png new file mode 100644 index 0000000000000000000000000000000000000000..29d9950f572d862c8104760ec0ed2c75452f9349 Binary files /dev/null and b/images/jvm/hsdb-ca5d06a0-1690-4a8f-98cb-aa6bd7800afe.png differ diff --git a/images/jvm/hsdb-cf39737a-7d6a-42de-b843-123cba1f96aa.png b/images/jvm/hsdb-cf39737a-7d6a-42de-b843-123cba1f96aa.png new file mode 100644 index 0000000000000000000000000000000000000000..f543e7345524d731e131824d79eb682916b1914f Binary files /dev/null and b/images/jvm/hsdb-cf39737a-7d6a-42de-b843-123cba1f96aa.png differ diff --git a/images/jvm/hsdb-e5f0f200-83fd-4529-b5d6-416f9a6f626b.png b/images/jvm/hsdb-e5f0f200-83fd-4529-b5d6-416f9a6f626b.png new file mode 100644 index 0000000000000000000000000000000000000000..50424d51bfd96e6bab81ebecadc956984aa4af7a Binary files /dev/null and b/images/jvm/hsdb-e5f0f200-83fd-4529-b5d6-416f9a6f626b.png differ diff --git a/images/jvm/hsdb-f07a9fc8-5744-4859-9df9-c3a1016e936a.png b/images/jvm/hsdb-f07a9fc8-5744-4859-9df9-c3a1016e936a.png new file mode 100644 index 0000000000000000000000000000000000000000..f2b3513f318055e24d98d5ef3ede4091fe2a6df9 Binary files /dev/null and b/images/jvm/hsdb-f07a9fc8-5744-4859-9df9-c3a1016e936a.png differ diff --git a/images/jvm/hsdb-f22359ab-b066-405f-a754-197ccbd36884.png b/images/jvm/hsdb-f22359ab-b066-405f-a754-197ccbd36884.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea914a269a392190694871d784be370b3a9135b Binary files /dev/null and b/images/jvm/hsdb-f22359ab-b066-405f-a754-197ccbd36884.png differ diff --git a/images/jvm/hsdb-f3c35027-2fe1-4b18-8a1c-b7243a9b5149.png b/images/jvm/hsdb-f3c35027-2fe1-4b18-8a1c-b7243a9b5149.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb133ad77081a140cc8f2083400c50ba0eec5a3 Binary files /dev/null and b/images/jvm/hsdb-f3c35027-2fe1-4b18-8a1c-b7243a9b5149.png differ diff --git a/images/jvm/jit-037b406d-1040-4bf8-976c-abf14a92402d.png b/images/jvm/jit-037b406d-1040-4bf8-976c-abf14a92402d.png new file mode 100644 index 0000000000000000000000000000000000000000..e2c270f87e51ad00f4fbfca7cf5e5cab71253177 Binary files /dev/null and b/images/jvm/jit-037b406d-1040-4bf8-976c-abf14a92402d.png differ diff --git a/images/jvm/jit-04b2d9ea-7add-4ee5-bf72-61a6bbaa58cf.png b/images/jvm/jit-04b2d9ea-7add-4ee5-bf72-61a6bbaa58cf.png new file mode 100644 index 0000000000000000000000000000000000000000..bd40d6594b7c72c77108e1e8e6f05b3615d66a34 Binary files /dev/null and b/images/jvm/jit-04b2d9ea-7add-4ee5-bf72-61a6bbaa58cf.png differ diff --git a/images/jvm/jit-04ca4a7e-46e7-4782-bb43-333aea31ed57.png b/images/jvm/jit-04ca4a7e-46e7-4782-bb43-333aea31ed57.png new file mode 100644 index 0000000000000000000000000000000000000000..6360c9199aaa46295e1212b2a39a2eb5e5abbe38 Binary files /dev/null and b/images/jvm/jit-04ca4a7e-46e7-4782-bb43-333aea31ed57.png differ diff --git a/images/jvm/jit-48e4ff65-07ec-487e-8b08-2f8fed1e56bd.png b/images/jvm/jit-48e4ff65-07ec-487e-8b08-2f8fed1e56bd.png new file mode 100644 index 0000000000000000000000000000000000000000..993780abafcb3ae5e3e6fb3cf6fc06ceb738ec1c Binary files /dev/null and b/images/jvm/jit-48e4ff65-07ec-487e-8b08-2f8fed1e56bd.png differ diff --git a/images/jvm/jit-4bf4d190-7fd2-4542-b948-0c85ee6963d2.png b/images/jvm/jit-4bf4d190-7fd2-4542-b948-0c85ee6963d2.png new file mode 100644 index 0000000000000000000000000000000000000000..e26ccdc21ae19e06648d887874302918f71e1654 Binary files /dev/null and b/images/jvm/jit-4bf4d190-7fd2-4542-b948-0c85ee6963d2.png differ diff --git a/images/jvm/jit-6158d832-9a0d-4af0-96ff-bf216a9cd5c6.png b/images/jvm/jit-6158d832-9a0d-4af0-96ff-bf216a9cd5c6.png new file mode 100644 index 0000000000000000000000000000000000000000..32afb7f3c41f8ffb665afdf28f1c06ffb1f50862 Binary files /dev/null and b/images/jvm/jit-6158d832-9a0d-4af0-96ff-bf216a9cd5c6.png differ diff --git a/images/jvm/jit-82ee887c-af7d-48d7-88a0-28960e564d4a.png b/images/jvm/jit-82ee887c-af7d-48d7-88a0-28960e564d4a.png new file mode 100644 index 0000000000000000000000000000000000000000..e2368e45e32bc39e5ec73971d57cd6945f3d966b Binary files /dev/null and b/images/jvm/jit-82ee887c-af7d-48d7-88a0-28960e564d4a.png differ diff --git a/images/jvm/jit-9a62fc02-1a6a-451e-bb2b-19fc086d5be0.png b/images/jvm/jit-9a62fc02-1a6a-451e-bb2b-19fc086d5be0.png new file mode 100644 index 0000000000000000000000000000000000000000..1d3788e5d6e0ca781122e01ec050c89a7660f2f4 Binary files /dev/null and b/images/jvm/jit-9a62fc02-1a6a-451e-bb2b-19fc086d5be0.png differ diff --git a/images/jvm/jit-a6cebc82-ed4d-4b6d-892a-c5b245d227ab.png b/images/jvm/jit-a6cebc82-ed4d-4b6d-892a-c5b245d227ab.png new file mode 100644 index 0000000000000000000000000000000000000000..98c6be9b43a94290645aab28e37faed447aaab24 Binary files /dev/null and b/images/jvm/jit-a6cebc82-ed4d-4b6d-892a-c5b245d227ab.png differ diff --git a/images/jvm/jit-f4d1b763-be02-4bb2-ab0e-45b1f0eb9550.png b/images/jvm/jit-f4d1b763-be02-4bb2-ab0e-45b1f0eb9550.png new file mode 100644 index 0000000000000000000000000000000000000000..f5669426d40c5b033bdba77b9bcb6ef3cb0e928e Binary files /dev/null and b/images/jvm/jit-f4d1b763-be02-4bb2-ab0e-45b1f0eb9550.png differ diff --git a/images/jvm/jit-f96da42a-568b-45ba-bed1-f4238ac32e14.png b/images/jvm/jit-f96da42a-568b-45ba-bed1-f4238ac32e14.png new file mode 100644 index 0000000000000000000000000000000000000000..197b435dde7e18a957e4a1e76bd68276a1b69476 Binary files /dev/null and b/images/jvm/jit-f96da42a-568b-45ba-bed1-f4238ac32e14.png differ diff --git a/images/jvm/jit-fb8b2bac-a7b9-45eb-bd28-05e35cf043ae.png b/images/jvm/jit-fb8b2bac-a7b9-45eb-bd28-05e35cf043ae.png new file mode 100644 index 0000000000000000000000000000000000000000..bfb3202ec3907f1e720fd44eb35a0b441fd8ac64 Binary files /dev/null and b/images/jvm/jit-fb8b2bac-a7b9-45eb-bd28-05e35cf043ae.png differ diff --git a/images/jvm/neicun-jiegou-4ea2a60a-05df-4ed1-8109-99ae23acefd1.png b/images/jvm/neicun-jiegou-4ea2a60a-05df-4ed1-8109-99ae23acefd1.png new file mode 100644 index 0000000000000000000000000000000000000000..06d048b5d381909d785a7e46f5dc9276a19d2f47 Binary files /dev/null and b/images/jvm/neicun-jiegou-4ea2a60a-05df-4ed1-8109-99ae23acefd1.png differ diff --git a/images/jvm/neicun-jiegou-dac0f4c1-8a7e-4309-a599-5664cdaf5016.png b/images/jvm/neicun-jiegou-dac0f4c1-8a7e-4309-a599-5664cdaf5016.png new file mode 100644 index 0000000000000000000000000000000000000000..e8f43fde48b37663304c402cae1367bd8415c6e1 Binary files /dev/null and b/images/jvm/neicun-jiegou-dac0f4c1-8a7e-4309-a599-5664cdaf5016.png differ diff --git a/images/jvm/neicun-jiegou-e33179f3-275b-44c9-87f6-802198f8f360.png b/images/jvm/neicun-jiegou-e33179f3-275b-44c9-87f6-802198f8f360.png new file mode 100644 index 0000000000000000000000000000000000000000..0767f66f7a035a559eaaa2d3f00d066df9fe2c93 Binary files /dev/null and b/images/jvm/neicun-jiegou-e33179f3-275b-44c9-87f6-802198f8f360.png differ diff --git a/images/jvm/problem-tools-031be661-e47e-44f0-9e33-34368b187662.png b/images/jvm/problem-tools-031be661-e47e-44f0-9e33-34368b187662.png new file mode 100644 index 0000000000000000000000000000000000000000..3f0a8a7df83c1c2606f53bf18861c58d872bd4af Binary files /dev/null and b/images/jvm/problem-tools-031be661-e47e-44f0-9e33-34368b187662.png differ diff --git a/images/jvm/problem-tools-059a3285-4a01-4f7a-a6ed-1cc5dcbf3f18.png b/images/jvm/problem-tools-059a3285-4a01-4f7a-a6ed-1cc5dcbf3f18.png new file mode 100644 index 0000000000000000000000000000000000000000..895568328b30e95c1389acc16a7639c55cecafd7 Binary files /dev/null and b/images/jvm/problem-tools-059a3285-4a01-4f7a-a6ed-1cc5dcbf3f18.png differ diff --git a/images/jvm/problem-tools-059e61f1-8263-4ee0-b36b-f117ecaf0a07.png b/images/jvm/problem-tools-059e61f1-8263-4ee0-b36b-f117ecaf0a07.png new file mode 100644 index 0000000000000000000000000000000000000000..b65443b6bb4b963d2ed8042db4d54c3b4a14502e Binary files /dev/null and b/images/jvm/problem-tools-059e61f1-8263-4ee0-b36b-f117ecaf0a07.png differ diff --git a/images/jvm/problem-tools-0ccc96dc-8053-4222-9824-b116f02776a4.png b/images/jvm/problem-tools-0ccc96dc-8053-4222-9824-b116f02776a4.png new file mode 100644 index 0000000000000000000000000000000000000000..35215c7d8afe152c6727a54d3c456a799d1ee3c3 Binary files /dev/null and b/images/jvm/problem-tools-0ccc96dc-8053-4222-9824-b116f02776a4.png differ diff --git a/images/jvm/problem-tools-2017daf6-832a-4673-b776-ad3380e47402.png b/images/jvm/problem-tools-2017daf6-832a-4673-b776-ad3380e47402.png new file mode 100644 index 0000000000000000000000000000000000000000..fbf15d3382fc9d0b7259bc12715532c76cc6da10 Binary files /dev/null and b/images/jvm/problem-tools-2017daf6-832a-4673-b776-ad3380e47402.png differ diff --git a/images/jvm/problem-tools-219b7cac-c9a9-4d47-8ecf-93a4a04fc1db.png b/images/jvm/problem-tools-219b7cac-c9a9-4d47-8ecf-93a4a04fc1db.png new file mode 100644 index 0000000000000000000000000000000000000000..ddb9df9aff2a891b4b770febc638427cb50e7ee7 Binary files /dev/null and b/images/jvm/problem-tools-219b7cac-c9a9-4d47-8ecf-93a4a04fc1db.png differ diff --git a/images/jvm/problem-tools-38d5c9da-e433-43d2-b1bc-3f3634e05497.png b/images/jvm/problem-tools-38d5c9da-e433-43d2-b1bc-3f3634e05497.png new file mode 100644 index 0000000000000000000000000000000000000000..bd478e8e8d4382d17fd5768090d139ab041d5c2f Binary files /dev/null and b/images/jvm/problem-tools-38d5c9da-e433-43d2-b1bc-3f3634e05497.png differ diff --git a/images/jvm/problem-tools-3f71397d-3ff6-430d-adf4-ff5ab9f111d5.png b/images/jvm/problem-tools-3f71397d-3ff6-430d-adf4-ff5ab9f111d5.png new file mode 100644 index 0000000000000000000000000000000000000000..97ce6da73c4eb21703adb3f506545a779ade34bc Binary files /dev/null and b/images/jvm/problem-tools-3f71397d-3ff6-430d-adf4-ff5ab9f111d5.png differ diff --git a/images/jvm/problem-tools-4fa6915b-d39c-4d6d-a6e7-edc989cac76f.png b/images/jvm/problem-tools-4fa6915b-d39c-4d6d-a6e7-edc989cac76f.png new file mode 100644 index 0000000000000000000000000000000000000000..63e31d9dfced7ae72a257be37bcb59e872858916 Binary files /dev/null and b/images/jvm/problem-tools-4fa6915b-d39c-4d6d-a6e7-edc989cac76f.png differ diff --git a/images/jvm/problem-tools-547b1b2c-9fb4-4d1d-9c72-013ec210f6a5.jpg b/images/jvm/problem-tools-547b1b2c-9fb4-4d1d-9c72-013ec210f6a5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c01aa09908063b6dc879760fd1bcd53ebdce45ee Binary files /dev/null and b/images/jvm/problem-tools-547b1b2c-9fb4-4d1d-9c72-013ec210f6a5.jpg differ diff --git a/images/jvm/problem-tools-5e42fe47-e1e6-4649-acb5-e17bd277a771.png b/images/jvm/problem-tools-5e42fe47-e1e6-4649-acb5-e17bd277a771.png new file mode 100644 index 0000000000000000000000000000000000000000..419a7bfc789e70a69d0701719730e311e4fa8649 Binary files /dev/null and b/images/jvm/problem-tools-5e42fe47-e1e6-4649-acb5-e17bd277a771.png differ diff --git a/images/jvm/problem-tools-6d57b323-9665-4453-9fee-ea3111ad8629.png b/images/jvm/problem-tools-6d57b323-9665-4453-9fee-ea3111ad8629.png new file mode 100644 index 0000000000000000000000000000000000000000..d8b745edf346d59ba25da93d1e20bd7e3073ba10 Binary files /dev/null and b/images/jvm/problem-tools-6d57b323-9665-4453-9fee-ea3111ad8629.png differ diff --git a/images/jvm/problem-tools-75acf4c8-393d-43d1-b208-04de1f0ba6bd.png b/images/jvm/problem-tools-75acf4c8-393d-43d1-b208-04de1f0ba6bd.png new file mode 100644 index 0000000000000000000000000000000000000000..b358b3df89af30749edcc5550d1eb92077d3ea43 Binary files /dev/null and b/images/jvm/problem-tools-75acf4c8-393d-43d1-b208-04de1f0ba6bd.png differ diff --git a/images/jvm/problem-tools-778d103e-b9e1-45d7-a583-b799d3b8c4d2.png b/images/jvm/problem-tools-778d103e-b9e1-45d7-a583-b799d3b8c4d2.png new file mode 100644 index 0000000000000000000000000000000000000000..d8b745edf346d59ba25da93d1e20bd7e3073ba10 Binary files /dev/null and b/images/jvm/problem-tools-778d103e-b9e1-45d7-a583-b799d3b8c4d2.png differ diff --git a/images/jvm/problem-tools-7fa6b7b2-28bf-46cb-8d52-5fe3cb75240a.png b/images/jvm/problem-tools-7fa6b7b2-28bf-46cb-8d52-5fe3cb75240a.png new file mode 100644 index 0000000000000000000000000000000000000000..36eef9d3ae2bf049416e2f25cc85caafc0fffa6d Binary files /dev/null and b/images/jvm/problem-tools-7fa6b7b2-28bf-46cb-8d52-5fe3cb75240a.png differ diff --git a/images/jvm/problem-tools-86c5ace2-7377-4d5a-a780-0a194e14c9a0.png b/images/jvm/problem-tools-86c5ace2-7377-4d5a-a780-0a194e14c9a0.png new file mode 100644 index 0000000000000000000000000000000000000000..19b121190d110d343d73d5efedfd946e754e86cd Binary files /dev/null and b/images/jvm/problem-tools-86c5ace2-7377-4d5a-a780-0a194e14c9a0.png differ diff --git a/images/jvm/problem-tools-96a70bab-5cee-4068-8ccb-1d35124abeea.png b/images/jvm/problem-tools-96a70bab-5cee-4068-8ccb-1d35124abeea.png new file mode 100644 index 0000000000000000000000000000000000000000..50a2a4e17fb369a1a9fc531f1b50712bc5e1d131 Binary files /dev/null and b/images/jvm/problem-tools-96a70bab-5cee-4068-8ccb-1d35124abeea.png differ diff --git a/images/jvm/problem-tools-b0742677-4ad0-4fd3-b985-054238af8865.png b/images/jvm/problem-tools-b0742677-4ad0-4fd3-b985-054238af8865.png new file mode 100644 index 0000000000000000000000000000000000000000..f964f151000782655d84690d67ae000131156f1b Binary files /dev/null and b/images/jvm/problem-tools-b0742677-4ad0-4fd3-b985-054238af8865.png differ diff --git a/images/jvm/problem-tools-c2a84c1d-e853-482a-88a5-27ef39da66a0.png b/images/jvm/problem-tools-c2a84c1d-e853-482a-88a5-27ef39da66a0.png new file mode 100644 index 0000000000000000000000000000000000000000..a481c4a39b4ca3786e890fec7aca09e7a57059f3 Binary files /dev/null and b/images/jvm/problem-tools-c2a84c1d-e853-482a-88a5-27ef39da66a0.png differ diff --git a/images/jvm/problem-tools-d258d260-65eb-48f9-8585-6bed74de5a47.png b/images/jvm/problem-tools-d258d260-65eb-48f9-8585-6bed74de5a47.png new file mode 100644 index 0000000000000000000000000000000000000000..37b21769e7b1e5a011706b5063f6f87e55d5263e Binary files /dev/null and b/images/jvm/problem-tools-d258d260-65eb-48f9-8585-6bed74de5a47.png differ diff --git a/images/jvm/problem-tools-dca6e1d0-f345-4e21-83b3-e0cf82e3d79a.png b/images/jvm/problem-tools-dca6e1d0-f345-4e21-83b3-e0cf82e3d79a.png new file mode 100644 index 0000000000000000000000000000000000000000..9838e98db38dcc35757558b7d3a8a3a57e79a5e8 Binary files /dev/null and b/images/jvm/problem-tools-dca6e1d0-f345-4e21-83b3-e0cf82e3d79a.png differ diff --git a/images/jvm/problem-tools-e80d0925-2dcf-4204-b46d-47312df2a673.png b/images/jvm/problem-tools-e80d0925-2dcf-4204-b46d-47312df2a673.png new file mode 100644 index 0000000000000000000000000000000000000000..082966d06b700aafd67f1773581cee8dd72060d7 Binary files /dev/null and b/images/jvm/problem-tools-e80d0925-2dcf-4204-b46d-47312df2a673.png differ diff --git a/images/jvm/problem-tools-f37517b7-20b4-4243-ae03-d41126ae43e5.png b/images/jvm/problem-tools-f37517b7-20b4-4243-ae03-d41126ae43e5.png new file mode 100644 index 0000000000000000000000000000000000000000..772cc4f27dd85a251b9ea8da7c78d0b630a13d06 Binary files /dev/null and b/images/jvm/problem-tools-f37517b7-20b4-4243-ae03-d41126ae43e5.png differ diff --git a/images/jvm/problem-tools-fd76ac30-53a5-4549-8206-18283f330758.png b/images/jvm/problem-tools-fd76ac30-53a5-4549-8206-18283f330758.png new file mode 100644 index 0000000000000000000000000000000000000000..30213f792d15c2e26dcde0d77a58e8a46b61b3b7 Binary files /dev/null and b/images/jvm/problem-tools-fd76ac30-53a5-4549-8206-18283f330758.png differ diff --git a/images/jvm/tujie-gc-2497947b-92b5-4a7c-9399-1909a3153660 b/images/jvm/tujie-gc-2497947b-92b5-4a7c-9399-1909a3153660 new file mode 100644 index 0000000000000000000000000000000000000000..32739554e464786a74ac3ad26e2416a82133a272 Binary files /dev/null and b/images/jvm/tujie-gc-2497947b-92b5-4a7c-9399-1909a3153660 differ diff --git a/images/jvm/tujie-gc-24b154be-4ad0-4cc7-87e9-a3035bc9e3c5.png b/images/jvm/tujie-gc-24b154be-4ad0-4cc7-87e9-a3035bc9e3c5.png new file mode 100644 index 0000000000000000000000000000000000000000..4a14633fb9d25c545c998002b189eeec0f763f31 Binary files /dev/null and b/images/jvm/tujie-gc-24b154be-4ad0-4cc7-87e9-a3035bc9e3c5.png differ diff --git a/images/jvm/tujie-gc-294701a5-1c50-4112-94a1-96a8bab80e34.png b/images/jvm/tujie-gc-294701a5-1c50-4112-94a1-96a8bab80e34.png new file mode 100644 index 0000000000000000000000000000000000000000..b0d7846916726ee1e86d73b4fdc106247526834f Binary files /dev/null and b/images/jvm/tujie-gc-294701a5-1c50-4112-94a1-96a8bab80e34.png differ diff --git a/images/jvm/tujie-gc-2b431315-26fa-4ea0-843a-c63ca568f960 b/images/jvm/tujie-gc-2b431315-26fa-4ea0-843a-c63ca568f960 new file mode 100644 index 0000000000000000000000000000000000000000..d43e989093b0f24a3e679db349eb433be4d1eb86 Binary files /dev/null and b/images/jvm/tujie-gc-2b431315-26fa-4ea0-843a-c63ca568f960 differ diff --git a/images/jvm/tujie-gc-590c5011-48c4-4543-bd26-6f14c2b8614b.png b/images/jvm/tujie-gc-590c5011-48c4-4543-bd26-6f14c2b8614b.png new file mode 100644 index 0000000000000000000000000000000000000000..880a0100cf07d2c7ae6030362eba97e45eb63159 Binary files /dev/null and b/images/jvm/tujie-gc-590c5011-48c4-4543-bd26-6f14c2b8614b.png differ diff --git a/images/jvm/tujie-gc-6cb31f8a-2eac-489c-88bd-fc643996ab49 b/images/jvm/tujie-gc-6cb31f8a-2eac-489c-88bd-fc643996ab49 new file mode 100644 index 0000000000000000000000000000000000000000..acbc76660dea35b79a1b01470a3651a722669842 Binary files /dev/null and b/images/jvm/tujie-gc-6cb31f8a-2eac-489c-88bd-fc643996ab49 differ diff --git a/images/jvm/tujie-gc-768f5a2c-6c81-4f76-b847-a41cc8413228.png b/images/jvm/tujie-gc-768f5a2c-6c81-4f76-b847-a41cc8413228.png new file mode 100644 index 0000000000000000000000000000000000000000..fd93700a8b43c4f01464322455d720385505d2bb Binary files /dev/null and b/images/jvm/tujie-gc-768f5a2c-6c81-4f76-b847-a41cc8413228.png differ diff --git a/images/jvm/tujie-gc-9858785a-c6aa-4d6d-a6cd-640d24dd27d0.png b/images/jvm/tujie-gc-9858785a-c6aa-4d6d-a6cd-640d24dd27d0.png new file mode 100644 index 0000000000000000000000000000000000000000..2282b76f9610f655f371e9e27ae72809b9024cd0 Binary files /dev/null and b/images/jvm/tujie-gc-9858785a-c6aa-4d6d-a6cd-640d24dd27d0.png differ diff --git a/images/jvm/tujie-gc-989889b6-adb4-4277-8c67-73d76658f744.png b/images/jvm/tujie-gc-989889b6-adb4-4277-8c67-73d76658f744.png new file mode 100644 index 0000000000000000000000000000000000000000..a07a2b3f0e214dc9bfaf949b15c4ee4ac59f0f7b Binary files /dev/null and b/images/jvm/tujie-gc-989889b6-adb4-4277-8c67-73d76658f744.png differ diff --git a/images/jvm/tujie-gc-aa9f883a-12db-4c8b-8391-3c289b53d804 b/images/jvm/tujie-gc-aa9f883a-12db-4c8b-8391-3c289b53d804 new file mode 100644 index 0000000000000000000000000000000000000000..66e37a657004b2ed723c7fb6cbb64cfbcd8ac32d Binary files /dev/null and b/images/jvm/tujie-gc-aa9f883a-12db-4c8b-8391-3c289b53d804 differ diff --git a/images/jvm/tujie-gc-dec96816-2912-4127-aaaa-a4d987123f52 b/images/jvm/tujie-gc-dec96816-2912-4127-aaaa-a4d987123f52 new file mode 100644 index 0000000000000000000000000000000000000000..78969b4e26ba36fa4cc3ad522188091d64bc6d53 Binary files /dev/null and b/images/jvm/tujie-gc-dec96816-2912-4127-aaaa-a4d987123f52 differ diff --git a/images/jvm/tujie-gc-df98a004-e233-4fb5-a31a-f422033ecfa7 b/images/jvm/tujie-gc-df98a004-e233-4fb5-a31a-f422033ecfa7 new file mode 100644 index 0000000000000000000000000000000000000000..dfab59d4633a9dd04079bc9c91d63c51a85ee901 Binary files /dev/null and b/images/jvm/tujie-gc-df98a004-e233-4fb5-a31a-f422033ecfa7 differ diff --git a/images/jvm/tujie-gc-e2560f59-9b24-4d16-88db-b6ac4d0b6ffe b/images/jvm/tujie-gc-e2560f59-9b24-4d16-88db-b6ac4d0b6ffe new file mode 100644 index 0000000000000000000000000000000000000000..cff006168188ffe992daf5e1327fc20701aaf69b Binary files /dev/null and b/images/jvm/tujie-gc-e2560f59-9b24-4d16-88db-b6ac4d0b6ffe differ diff --git a/images/jvm/tujie-gc-efe9657b-c7a6-48a8-9037-0e709b1d236c b/images/jvm/tujie-gc-efe9657b-c7a6-48a8-9037-0e709b1d236c new file mode 100644 index 0000000000000000000000000000000000000000..6088e035d18ac786a79a454c6d70792f704d3310 Binary files /dev/null and b/images/jvm/tujie-gc-efe9657b-c7a6-48a8-9037-0e709b1d236c differ diff --git a/images/jvm/zijiema-zhiling-04e166ae-13c7-4025-804a-be88e2923a50.png b/images/jvm/zijiema-zhiling-04e166ae-13c7-4025-804a-be88e2923a50.png new file mode 100644 index 0000000000000000000000000000000000000000..ba9b08b75dd773eeb16c658e040ef6b50a82ed8a Binary files /dev/null and b/images/jvm/zijiema-zhiling-04e166ae-13c7-4025-804a-be88e2923a50.png differ diff --git a/images/jvm/zijiema-zhiling-05bfae95-2a33-402c-9041-570093729c42.png b/images/jvm/zijiema-zhiling-05bfae95-2a33-402c-9041-570093729c42.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ba0913a5905099c8673e4403033a788bfbca9e Binary files /dev/null and b/images/jvm/zijiema-zhiling-05bfae95-2a33-402c-9041-570093729c42.png differ diff --git a/images/jvm/zijiema-zhiling-0c3e47c6-1e25-4926-a838-20cf146a8993.png b/images/jvm/zijiema-zhiling-0c3e47c6-1e25-4926-a838-20cf146a8993.png new file mode 100644 index 0000000000000000000000000000000000000000..e907bcfb20780565bb6922cd625dc0c85b418a85 Binary files /dev/null and b/images/jvm/zijiema-zhiling-0c3e47c6-1e25-4926-a838-20cf146a8993.png differ diff --git a/images/jvm/zijiema-zhiling-270c314d-872b-43b0-861f-417eafc046fd.png b/images/jvm/zijiema-zhiling-270c314d-872b-43b0-861f-417eafc046fd.png new file mode 100644 index 0000000000000000000000000000000000000000..bace80bc78c4b2b3cea4b15e3613ae9143ad4462 Binary files /dev/null and b/images/jvm/zijiema-zhiling-270c314d-872b-43b0-861f-417eafc046fd.png differ diff --git a/images/jvm/zijiema-zhiling-37513fa2-fdba-45db-adfc-c18225c6ff8b.png b/images/jvm/zijiema-zhiling-37513fa2-fdba-45db-adfc-c18225c6ff8b.png new file mode 100644 index 0000000000000000000000000000000000000000..65311d4eedb4b765b8ca17c8ff11a912f41d9378 Binary files /dev/null and b/images/jvm/zijiema-zhiling-37513fa2-fdba-45db-adfc-c18225c6ff8b.png differ diff --git a/images/jvm/zijiema-zhiling-598e4204-fd77-425b-b536-1e001cda8e13.png b/images/jvm/zijiema-zhiling-598e4204-fd77-425b-b536-1e001cda8e13.png new file mode 100644 index 0000000000000000000000000000000000000000..58658b79c3c31d4536f9c99dd180e67045974499 Binary files /dev/null and b/images/jvm/zijiema-zhiling-598e4204-fd77-425b-b536-1e001cda8e13.png differ diff --git a/images/jvm/zijiema-zhiling-5de34f26-52ad-4e07-a20d-91ea92038984.png b/images/jvm/zijiema-zhiling-5de34f26-52ad-4e07-a20d-91ea92038984.png new file mode 100644 index 0000000000000000000000000000000000000000..eed360aba0945885748d8ea70e70a0662b981774 Binary files /dev/null and b/images/jvm/zijiema-zhiling-5de34f26-52ad-4e07-a20d-91ea92038984.png differ diff --git a/images/jvm/zijiema-zhiling-642ca54e-5808-428d-9840-ebf478e95c17.png b/images/jvm/zijiema-zhiling-642ca54e-5808-428d-9840-ebf478e95c17.png new file mode 100644 index 0000000000000000000000000000000000000000..2b80b78d385ab6471ea49e020879d08dbf323b68 Binary files /dev/null and b/images/jvm/zijiema-zhiling-642ca54e-5808-428d-9840-ebf478e95c17.png differ diff --git a/images/jvm/zijiema-zhiling-70441cfc-7c6e-4a5e-b0dd-818fc3fa1a67.png b/images/jvm/zijiema-zhiling-70441cfc-7c6e-4a5e-b0dd-818fc3fa1a67.png new file mode 100644 index 0000000000000000000000000000000000000000..f9446ea28d0077a911f904e05a5ba3bcd4091c8d Binary files /dev/null and b/images/jvm/zijiema-zhiling-70441cfc-7c6e-4a5e-b0dd-818fc3fa1a67.png differ diff --git a/images/jvm/zijiema-zhiling-79d74946-ce9e-41d4-b889-bda861f847bc.png b/images/jvm/zijiema-zhiling-79d74946-ce9e-41d4-b889-bda861f847bc.png new file mode 100644 index 0000000000000000000000000000000000000000..1527caa1782f2e3fe2a305a40ee7a31959450417 Binary files /dev/null and b/images/jvm/zijiema-zhiling-79d74946-ce9e-41d4-b889-bda861f847bc.png differ diff --git a/images/jvm/zijiema-zhiling-8125da3d-876c-43fe-8347-cb2341408088.png b/images/jvm/zijiema-zhiling-8125da3d-876c-43fe-8347-cb2341408088.png new file mode 100644 index 0000000000000000000000000000000000000000..2da050907dd96219c80d5cee332de59507a184c8 Binary files /dev/null and b/images/jvm/zijiema-zhiling-8125da3d-876c-43fe-8347-cb2341408088.png differ diff --git a/images/jvm/zijiema-zhiling-879da2f2-fb72-48a9-985e-5a28a9fc8814.png b/images/jvm/zijiema-zhiling-879da2f2-fb72-48a9-985e-5a28a9fc8814.png new file mode 100644 index 0000000000000000000000000000000000000000..48479f17e044ddd8d44639af1846d0cbcb450d3c Binary files /dev/null and b/images/jvm/zijiema-zhiling-879da2f2-fb72-48a9-985e-5a28a9fc8814.png differ diff --git a/images/jvm/zijiema-zhiling-a08c20cb-c148-47c9-91e2-df37e68989a9.png b/images/jvm/zijiema-zhiling-a08c20cb-c148-47c9-91e2-df37e68989a9.png new file mode 100644 index 0000000000000000000000000000000000000000..cc27f9d5ea09d16b1361faaf3c4673ff274a4484 Binary files /dev/null and b/images/jvm/zijiema-zhiling-a08c20cb-c148-47c9-91e2-df37e68989a9.png differ diff --git a/images/jvm/zijiema-zhiling-b34fc802-18bb-46a1-8d24-de2087c9b6bf.png b/images/jvm/zijiema-zhiling-b34fc802-18bb-46a1-8d24-de2087c9b6bf.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d2f6c4aecc340353d9326f1737d2c9f979ba6e Binary files /dev/null and b/images/jvm/zijiema-zhiling-b34fc802-18bb-46a1-8d24-de2087c9b6bf.png differ diff --git a/images/jvm/zijiema-zhiling-bfab6edd-d63f-45a7-8838-997e7630fa2a.png b/images/jvm/zijiema-zhiling-bfab6edd-d63f-45a7-8838-997e7630fa2a.png new file mode 100644 index 0000000000000000000000000000000000000000..a7c28d4fbb48f7487608dc0d9e8ce390eb57577f Binary files /dev/null and b/images/jvm/zijiema-zhiling-bfab6edd-d63f-45a7-8838-997e7630fa2a.png differ diff --git a/images/jvm/zijiema-zhiling-d0561d5c-ae21-48e7-9e7c-4aae87d02f56.png b/images/jvm/zijiema-zhiling-d0561d5c-ae21-48e7-9e7c-4aae87d02f56.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee0170f13967442f7d8e30a1a50cf4bfd08951e Binary files /dev/null and b/images/jvm/zijiema-zhiling-d0561d5c-ae21-48e7-9e7c-4aae87d02f56.png differ diff --git a/images/jvm/zijiema-zhiling-d4f9a680-1364-4af9-9474-c0763c9bc6f7.png b/images/jvm/zijiema-zhiling-d4f9a680-1364-4af9-9474-c0763c9bc6f7.png new file mode 100644 index 0000000000000000000000000000000000000000..f4848f8320021f86426bedf915be905119ba6b19 Binary files /dev/null and b/images/jvm/zijiema-zhiling-d4f9a680-1364-4af9-9474-c0763c9bc6f7.png differ diff --git a/images/jvm/zijiema-zhiling-d955468c-d07d-47cd-b82b-c03ecea8753d.png b/images/jvm/zijiema-zhiling-d955468c-d07d-47cd-b82b-c03ecea8753d.png new file mode 100644 index 0000000000000000000000000000000000000000..6fba3ab2717845295349285d0ffcd4dca2db6e52 Binary files /dev/null and b/images/jvm/zijiema-zhiling-d955468c-d07d-47cd-b82b-c03ecea8753d.png differ diff --git a/images/jvm/zijiema-zhiling-e8fa6685-b3d4-4f42-8fc5-8a4d8a9efe7b.png b/images/jvm/zijiema-zhiling-e8fa6685-b3d4-4f42-8fc5-8a4d8a9efe7b.png new file mode 100644 index 0000000000000000000000000000000000000000..90b15a9eca8a148d2d246815814e027d0cb7803c Binary files /dev/null and b/images/jvm/zijiema-zhiling-e8fa6685-b3d4-4f42-8fc5-8a4d8a9efe7b.png differ diff --git a/images/jvm/zongjie-04b18ddb-3457-4e46-ba53-78237d234e37.png b/images/jvm/zongjie-04b18ddb-3457-4e46-ba53-78237d234e37.png new file mode 100644 index 0000000000000000000000000000000000000000..811edfead82cafa0b4ec0951396032aa43434864 Binary files /dev/null and b/images/jvm/zongjie-04b18ddb-3457-4e46-ba53-78237d234e37.png differ diff --git a/images/jvm/zongjie-1d779fca-b6a4-4982-b746-2a8db7805645.png b/images/jvm/zongjie-1d779fca-b6a4-4982-b746-2a8db7805645.png new file mode 100644 index 0000000000000000000000000000000000000000..c380974bfd32c2bbc6c4b02359c04b861e407cc9 Binary files /dev/null and b/images/jvm/zongjie-1d779fca-b6a4-4982-b746-2a8db7805645.png differ diff --git a/images/jvm/zongjie-1fa20f99-d203-42d6-982c-f1bd66a0c929.png b/images/jvm/zongjie-1fa20f99-d203-42d6-982c-f1bd66a0c929.png new file mode 100644 index 0000000000000000000000000000000000000000..d463018457565aac2053edcfa40ffb27b822f7ce Binary files /dev/null and b/images/jvm/zongjie-1fa20f99-d203-42d6-982c-f1bd66a0c929.png differ diff --git a/images/jvm/zongjie-2188c350-fdb8-4fee-b2f0-5311795f386b.png b/images/jvm/zongjie-2188c350-fdb8-4fee-b2f0-5311795f386b.png new file mode 100644 index 0000000000000000000000000000000000000000..486d332a1f4f0a6cd469311b5007d2b909571247 Binary files /dev/null and b/images/jvm/zongjie-2188c350-fdb8-4fee-b2f0-5311795f386b.png differ diff --git a/images/jvm/zongjie-30dd34d5-27df-4a6f-b391-5a7928dfb3ab.png b/images/jvm/zongjie-30dd34d5-27df-4a6f-b391-5a7928dfb3ab.png new file mode 100644 index 0000000000000000000000000000000000000000..385784bee5fd9d787a73aee71008862d65b44f70 Binary files /dev/null and b/images/jvm/zongjie-30dd34d5-27df-4a6f-b391-5a7928dfb3ab.png differ diff --git a/images/jvm/zongjie-3cf7a78a-d541-49af-929a-4bf8f4f0edd9.png b/images/jvm/zongjie-3cf7a78a-d541-49af-929a-4bf8f4f0edd9.png new file mode 100644 index 0000000000000000000000000000000000000000..137c4c6f0dcb50ed9c77760cfc4c516cb433ab4e Binary files /dev/null and b/images/jvm/zongjie-3cf7a78a-d541-49af-929a-4bf8f4f0edd9.png differ diff --git a/images/jvm/zongjie-7ad8d755-53f2-422a-9cea-c792b0579d8b.png b/images/jvm/zongjie-7ad8d755-53f2-422a-9cea-c792b0579d8b.png new file mode 100644 index 0000000000000000000000000000000000000000..be377e36189e847cc70114186d48547b558955de Binary files /dev/null and b/images/jvm/zongjie-7ad8d755-53f2-422a-9cea-c792b0579d8b.png differ diff --git a/images/jvm/zongjie-7d489254-f1e0-4feb-bd4a-af129767a787.png b/images/jvm/zongjie-7d489254-f1e0-4feb-bd4a-af129767a787.png new file mode 100644 index 0000000000000000000000000000000000000000..a8c0dacd410593648f7176c44a68bb2104f28b56 Binary files /dev/null and b/images/jvm/zongjie-7d489254-f1e0-4feb-bd4a-af129767a787.png differ diff --git a/images/jvm/zongjie-ae8c47c7-538b-426a-85e4-d422d1c37683.png b/images/jvm/zongjie-ae8c47c7-538b-426a-85e4-d422d1c37683.png new file mode 100644 index 0000000000000000000000000000000000000000..2e325fb3473025f6780d71582ad0776cb0d6a5cf Binary files /dev/null and b/images/jvm/zongjie-ae8c47c7-538b-426a-85e4-d422d1c37683.png differ diff --git a/images/jvm/zongjie-afb11e2b-f457-4a19-bb21-f659756061ec.png b/images/jvm/zongjie-afb11e2b-f457-4a19-bb21-f659756061ec.png new file mode 100644 index 0000000000000000000000000000000000000000..b1934d695cf49327fafed34f4c5af8de9ea5fcfe Binary files /dev/null and b/images/jvm/zongjie-afb11e2b-f457-4a19-bb21-f659756061ec.png differ diff --git a/images/jvm/zongjie-b199ece2-8de2-4f24-b50a-ea0c0d16bd7b.png b/images/jvm/zongjie-b199ece2-8de2-4f24-b50a-ea0c0d16bd7b.png new file mode 100644 index 0000000000000000000000000000000000000000..cfb1607670ff44def57e368a442a439b94ec654a Binary files /dev/null and b/images/jvm/zongjie-b199ece2-8de2-4f24-b50a-ea0c0d16bd7b.png differ diff --git a/images/jvm/zongjie-c1fcdc37-4e5a-4ed3-94b1-ad4afa2dba7c.png b/images/jvm/zongjie-c1fcdc37-4e5a-4ed3-94b1-ad4afa2dba7c.png new file mode 100644 index 0000000000000000000000000000000000000000..9664d113379e4f78e70e5beb9e76ceed235fa724 Binary files /dev/null and b/images/jvm/zongjie-c1fcdc37-4e5a-4ed3-94b1-ad4afa2dba7c.png differ diff --git a/images/jvm/zongjie-e0f5da26-6e46-4f9d-bfcc-0842cc7079e7.png b/images/jvm/zongjie-e0f5da26-6e46-4f9d-bfcc-0842cc7079e7.png new file mode 100644 index 0000000000000000000000000000000000000000..f4050ff451175760e8479f9145cb83c2f66a199f Binary files /dev/null and b/images/jvm/zongjie-e0f5da26-6e46-4f9d-bfcc-0842cc7079e7.png differ diff --git a/images/jvm/zongjie-e154964a-9a0a-46de-bf37-75b483956d6c.png b/images/jvm/zongjie-e154964a-9a0a-46de-bf37-75b483956d6c.png new file mode 100644 index 0000000000000000000000000000000000000000..b326f1eee17481574b22bab93f0eeb9d93c43730 Binary files /dev/null and b/images/jvm/zongjie-e154964a-9a0a-46de-bf37-75b483956d6c.png differ diff --git a/images/jvm/zongjie-e674c49f-c55b-4eba-95ea-34be62d55a78.png b/images/jvm/zongjie-e674c49f-c55b-4eba-95ea-34be62d55a78.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd1d9de9c7a1ff9c3f1da7834e9f4521747fbdc Binary files /dev/null and b/images/jvm/zongjie-e674c49f-c55b-4eba-95ea-34be62d55a78.png differ diff --git a/images/jvm/zongjie-ec6ec994-6fe4-4d5b-890c-7f31b5a607a0.png b/images/jvm/zongjie-ec6ec994-6fe4-4d5b-890c-7f31b5a607a0.png new file mode 100644 index 0000000000000000000000000000000000000000..cfb1607670ff44def57e368a442a439b94ec654a Binary files /dev/null and b/images/jvm/zongjie-ec6ec994-6fe4-4d5b-890c-7f31b5a607a0.png differ diff --git a/images/jvm/zongjie-f1325549-5689-4398-a39c-c0a6836f6077.png b/images/jvm/zongjie-f1325549-5689-4398-a39c-c0a6836f6077.png new file mode 100644 index 0000000000000000000000000000000000000000..45f37486a23ed90a71f3062b587b7b22b05e8443 Binary files /dev/null and b/images/jvm/zongjie-f1325549-5689-4398-a39c-c0a6836f6077.png differ diff --git a/images/jvm/zongjie-f4572b93-f7f3-41cc-9901-93816e79c789.png b/images/jvm/zongjie-f4572b93-f7f3-41cc-9901-93816e79c789.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd2d26641f1ea07c56054bba14c74b8747db02c Binary files /dev/null and b/images/jvm/zongjie-f4572b93-f7f3-41cc-9901-93816e79c789.png differ diff --git a/images/jvm/zongjie-f696f4a8-af51-4e28-9d72-c2f6b1e5b3db.png b/images/jvm/zongjie-f696f4a8-af51-4e28-9d72-c2f6b1e5b3db.png new file mode 100644 index 0000000000000000000000000000000000000000..5393daa71a19654de4f0df25232220a5b7941831 Binary files /dev/null and b/images/jvm/zongjie-f696f4a8-af51-4e28-9d72-c2f6b1e5b3db.png differ diff --git a/images/jvm/zongjie-f6b5eb22-a5af-40c0-8c80-00fdd6d16b1d.png b/images/jvm/zongjie-f6b5eb22-a5af-40c0-8c80-00fdd6d16b1d.png new file mode 100644 index 0000000000000000000000000000000000000000..290a8a9061867230b72e931c2a83bc9cdfd2bd7f Binary files /dev/null and b/images/jvm/zongjie-f6b5eb22-a5af-40c0-8c80-00fdd6d16b1d.png differ