- classLoader
- 字节码
- 内存区域划分
- 垃圾回收
一. jvm 内存划分为以下几个区域
- 虚拟机栈 : stack frame 栈帧
- 程序计数器 : program counter
- 本地方法栈 : c ++ 等实现
- 堆 : 最大的一块共享内存区域 , new object 的实例 。通过引用(在栈上) 指向实例。 与堆密切相关的是垃圾收集器, 几乎所有的现在垃圾回收器都采用了分代算法, 堆空间也针对此进行了划分 。 新生代和老年代 Eden, from survivor ,to survivor (默认按照80 , 10 ,10 的比例进行划分)
- 方法区 : 主要存储一些元信息,其中包括 class信息 等 ,有称为永久代 (jdk1.8 开始废弃,进而被元空间取代 ),很少会被垃圾回收
- 直接内存: 堆外内存,不是jvm直接管理 ,操作系统管理 . nio直接相关,DirectByteBuffer 是堆外内存
虚拟机栈,程序计数器 和 本地方法栈 都是内存私有的 。
堆是虚拟机中最大的一块内存区域,我们通过new关键字创建的对象,绝大多数都会在堆上面分配内存 ,然后会在栈上通过引用去指向它。
堆上的对象由 数据区和元数据(比如class对象唯一)2 部分组成 , 并且在不同的虚拟机上面会有不同的实现 如图所示:
- 堆上实例指向数据空间和元数据
- 堆上的实指向元数据并包括数据空间
二. new关键字创建对象的流程
- 在堆内存创建对象实例
- 为对象实例成员变量赋初值
- 返回对象引用
对象在内存中的布局:
- 对象头
- 实例数据
- 对齐填充(可选)
引用对象的方式
使用句柄
使用直接指针
通过实例模拟一个outofmemory
configuration : vmoptions :
-Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError
1 | public class Test01 { |
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to java_pid19782.hprof ...
Heap dump file created [8972643 bytes in 0.075 secs]
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.java.memory.Test01.main(Test01.java:25)
一些重要工具的使用:
- jvisualvm 进行实例分析
- jconsole 进行实例分析
- jmap命令行工具的使用,可以查看当前运行的java进程的 classloader ,heap信息 等
- jstat 命令行工具 可以 查看gc等。 mc(current metaspace capcity) ,mu(metaspace used 已经使用的)信息
- jcmd 命令
jcmd pid VM.flags jvm信息
jcmd pid help 列而可以对当前pid进行的操作 - jps 列出所有java进程的信息
- jstack 查看,导出堆栈信息
- jmc java misson control
- jhat 查看hprof 文件信息