JVM是JAVA虚拟机的英文缩写,其本质就是一台虚拟机。Java虚拟机与其他虚拟机有何区别?其为解决何种问题而诞生?先看官网上提供的图,如下:
可以很清晰地观察到JVM,JRE,JDK之间的关系及JVM的核心地位(其与操作系统交互,完成自动内存管理):
接下来就开始JVM的识别之旅。实际上JVM是对java虚拟机规范的具体实现,而且市面上有的实现还挺多。上图中使用的是HotSpot VM,我们以该实现为范例认识和理解JVM。
很多时候,有人会疑惑为什么要对JVM有深刻地理解?实际工作多年后,很多时候你要解决一个问题必须深入到字节码层次去分析,你才能得到准确的结论,而字节码就是虚拟机的一部分。这也是我们需要深入理解JVM的一个原因——更好地解决实际生产中出现的问题。
从字节码的维度去分析解决问题,其本质应该是从内存这个维度去分析解决问题。下图是JVM整体结构:
其中内存部分就是运行时数据区,即虚拟机的内存结构。该结构具体如下图:
其中线程私有的: 1)程序计数器 2)虚拟机栈 3)本地方法栈
线程共享的: 1)堆 2)方法区
直接内存也是线程共享,但其不属于运行时数据区的一部分。下面就内存部分,分结构介绍:
一、计数器PC Register
二、Java Stacks
该结构可配置大小,可以优化的一个点:
-Xss 为jvm启动的每个线程分配的内存大小:
Linux/x64 (64-bit): 1024 KB
macOS (64-bit): 1024 KB
Oracle Solaris/x64 (64-bit): 1024 KB
Windows: The default value depends on virtual memory
-Xss1m
-Xss1024k
-Xss1048576
局部变量
三、Native Method Stacks
其为为虚拟机使用到的本地(Native) 方法服务。
在Java虚拟机规范中,对本地方法栈这块区域,与Java虚拟机栈一样,规定了两种类型的异常:
(1)StackOverFlowError :线程请求的栈深度>所允许的深度。
(2)OutOfMemoryError:本地方法栈扩展时无法申请到足够的内存。
四、Heap
1)堆大小设置
内存大小-Xmx/-Xms,使用示例: -Xmx20m -Xms5m
堆分配过程
五、Metaspace
其参数设置如下:
-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。如果没有使用该参数来设置类的元数据的大小,其最大可利用空间是整个系统内存的可用空间。JVM也可以增加本地内存空间来满足类元数据信息的存储。但是如果没有设置最大值,则可能存在bug导致Metaspace的空间在不停的扩展,会导致机器的内存不足;进而可能出现swap内存被耗尽;最终导致进程直接被系统直接kill掉。如果设置了该参数,当Metaspace剩余空间不足,会抛出:java.lang.OutOfMemoryError: Metaspace space
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集
查看该区值:
未完,待续……