【jvm】内存结构

一。程序计数器

  程序计数器是线程私有的。

  每个线程都拥有一个程序计数器,用来记住吓一条指令的执行地址。

  程序计数器不会发生内存溢出,也就是oom。

二。虚拟机栈

  虚拟机栈是线程私有的。

  虚拟机栈是用来存放栈帧的地方。 

    栈帧是每一次调用方法时所占用的内存。

    栈帧中的结构有:

    局部变量表: 用来存储方法中的局部变量。

      基本数据类型数值。

      reference

      returnAddress

    操作数栈: 当运行字节码文件时,会将数据临时存储其中(iload)。

    动态链接: 在多态的情况下,当编译源代码时无法确定对象的类型,所以只能在运行时才能确定对象,指向常量池中的方法,将符号引用变成直接引用。

    方法出口: 也就是方法返回地址,正常结束时返回地址,如果报错时返回异常地址。

三。本地方法栈

  本地方法栈是线程私有。

  本地方法栈时用来为虚拟机的native方法提供服务,这些方法由c++编写。

四。堆

  堆不是线程私有的,是线程共享。

  堆是存放各种对象的地方,也包括类对象,也是jvm垃圾回收机制回收的重点方法。

  在1.7之后,stringTable也放入了堆中,便于垃圾回收(fullGC)。

  堆内存诊断工具:

  1. jps 工具 查看当前系统中有哪些 java 进程

  2. jmap 工具 查看堆内存占用情况 jmap - heap 进程id

  3. jconsole 工具 图形界面的,多功能的监测工具,可以连续监测

五。方法区

  方法区是一种概念,存储着一些元数据。

  在1.6及之前实现方式是永久代,是放在堆中。

  在1.8以后,将其放在了元空间,元空间是在本地内存中。

  方法区的数据有:

    运行时常量池, 

      一般存文字字符串 

      final常量值

      基本类型数据值。

      类的结构全限定名。

      字段名称和描述符。

      方法名称和描述符。

    类信息

      类属性(field)

      方法

六。直接内存

  直接内存也叫Direct Memory,常见于 NIO 操作时,用于数据缓冲区 分配回收成本较高,但读写性能高 不受 JVM 内存回收管理。

 

   当需要读取磁盘信息时,一般流程是需要加载到系统内存,再从系统内存加载到java内存,随后才被java代码处理。有了直接内存可以提高io的速度。

  分配和回收

  使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法 ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦 ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调 用 freeMemory 来释放直接内存。