jvm 内存区域五部分:

  • 程序计数器(PC)
  • 虚拟机栈(JVM Stack)
  • 本地方法栈(Native Method Stack)
  • Java 堆内存(Java Heap)
  • 方法区(Method Area)

  • 程序计数器

CPU 程序计数器寄存器(x86为eip,ARM为R15),存CPU下一条指令地址,每一条指令执行时,CPU自动修改PC至下一条指令的地址

JVM 每线程有自己私有的 PC,存当前执行bytecode地址

若执行的为native方法,则PC的值为undefined

  • 虚拟机栈

也是线程私有,与线程同时创建。描述了方法执行的内存模型:存局部变量表、操作数栈、动态链接、方法出口等信息

栈帧可在系统的堆上分配内存(是系统的Heap而不是Java Heap)。Java虚拟机栈所使用的内存不需要保证是连续的

  • 本地方法栈

HotSpot JVM中Java虚拟机栈和本地方法栈合二为一

供各线程共享,几乎所有对象实例和数组实例都在Java堆上分配,随JIT及逃逸分析技术发展,也可能会被优化为栈上分配)

GC收集主要区域

内存回收角度来看,分新生代和老年代,再细分可以分为Eden Space,From Survivor Space,To Survivor Space区

  • 方法区

线程共享的,储存每一个类的结构信息,如运行时常量池(runtime constant pool)、字段和方法数据、构造函数和普通方法的字节码内容,还包括一些初始化的时候用到的特殊方法。方法区是堆的逻辑部分

1.7 前HotSpot JVM中,方法区位于永久代(Permanent Generation,PermGen)

永久代内可能会发生内存泄露或溢出等问题而导致的java.lang.OutOfMemoryError: PermGen ,1.7中把字符串常量,符号引用等移出了永久代

Java 8,永久代彻底地移出JVM,取而代之的是元空间(Metaspace)

  • 运行时常量池

class文件中每一个类或接口的常量池表的运行时表示形式,是方法区的一部分,包括若干种不同的常量

常量池表存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放

运行时常量池具有动态性,运行期间也可以将新的量放到运行时常量池中,典型的应用是String类的intern方法:

public native String intern()

1.7 字符串常量和符号引用等就被移出永久代:

  • 符号引用迁移至系统堆内存(Native Heap)
  • 字符串字面量迁移至Java堆(Java Heap)

http://www.sczyh30.com/posts/Java/jvm-memory/