内存区域
JVM就是二进制字节码的运行环境,负责装载字节码到内部,解释/编译为对应平台上的机器指令执行。JVM运行在操作系统上,与计算机硬件没有直接交互。
本地方法栈:
被native关键字修饰的方法会进入本地方法栈,调用JNI(本地方法接口),JNI可以调用C/C++程序。
程序计数器:
每一个线程都有一个私有的程序计数器,指向方法区中的方法字节码,在执行引擎读取下一条指令。
方法区:
存储类信息、常量、静态变量、类中的方法信息以及编译器编译后的代码等数据。(static final 类信息 常量池)
方法区中有个区域叫常量池,用于存放静态编译产生的字面量和符号引用。运行时生成的常量也会存在这个常量池中,比如String的intern方法。它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来。
虚拟机栈:
生命周期和线程同步,负责程序的运行。每个方法在执行时都会创建一个栈帧用于存储局部变量、动态链接、方法出口等信息。每一个方法从调用到执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。
堆:
堆中存储了对象实例, 一个JVM只有一个堆,大小可以改变。
堆中分为三个区域:
1.新生代
新生代又分为生成区(伊甸园区)和幸存区(from、to)
2.老年代
3.永久代
注: jdk7之前:方法区位于永久代,永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值,不可变;
jdk7:存储在永久代的部分数据就已经转移到Java Heap或者Native memory。但永久代仍存在于JDK 中,并没有完全移除,譬如符号引用(Symbols)转移到了native memory;字符串常量池(interned strings)转移到了Java heap;类的静态变量(class statics variables )转移到了Java heap;
jdk8:仍然保留方法区的概念,只不过实现方式不同。取消永久代,方法区存放于元空间(Metaspace),元空间仍然与堆不相连,但与堆共享物理内存,逻辑上可认为在堆中。