JVM是JAVA虚拟机的英文缩写,其本质就是一台虚拟机。Java虚拟机与其他虚拟机有何区别?其为解决何种问题而诞生?先看官网上提供的图,如下:

    初识JVM_元数据

   可以很清晰地观察到JVM,JRE,JDK之间的关系及JVM的核心地位(其与操作系统交互,完成自动内存管理):

        初识JVM_字节码_02

  接下来就开始JVM的识别之旅。实际上JVM是对java虚拟机规范的具体实现,而且市面上有的实现还挺多。上图中使用的是HotSpot VM,我们以该实现为范例认识和理解JVM。

  很多时候,有人会疑惑为什么要对JVM有深刻地理解?实际工作多年后,很多时候你要解决一个问题必须深入到字节码层次去分析,你才能得到准确的结论,而字节码就是虚拟机的一部分。这也是我们需要深入理解JVM的一个原因——更好地解决实际生产中出现的问题。

  从字节码的维度去分析解决问题,其本质应该是从内存这个维度去分析解决问题。下图是JVM整体结构:

    初识JVM_java虚拟机_03

   其中内存部分就是运行时数据区,即虚拟机的内存结构。该结构具体如下图:

     初识JVM_本地方法_04

      初识JVM_本地方法_05

  其中线程私有的:  1)程序计数器  2)虚拟机栈  3)本地方法栈

  线程共享的: 1)堆 2)方法区

  直接内存也是线程共享,但其不属于运行时数据区的一部分。下面就内存部分,分结构介绍:

  一、计数器PC Register

    初识JVM_垃圾收集_06

  二、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

    局部变量

      初识JVM_java虚拟机_07

  三、Native Method Stacks

    其为为虚拟机使用到的本地(Native) 方法服务。

  在Java虚拟机规范中,对本地方法栈这块区域,与Java虚拟机栈一样,规定了两种类型的异常:
    (1)StackOverFlowError :线程请求的栈深度>所允许的深度。
    (2)OutOfMemoryError:本地方法栈扩展时无法申请到足够的内存。

  四、Heap

    1)堆大小设置

      内存大小-Xmx/-Xms,使用示例: -Xmx20m -Xms5m

    堆分配过程

      初识JVM_本地方法_08

  五、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剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

     查看该区值:

      初识JVM_元数据_09

 

 

 

  
  未完,待续……