JAVA内存模型

线程私有:虚拟机栈,本地方法栈,程序计数器

线程共享:方法区,堆

程序计数器

当前线程所执行的字节码的行号指示器。

如果线程执行的是Java方法,则这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果执行的是Native方法,这个计数器值应为空(Undefined)

虚拟机栈

虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行时,Java虚拟机都会同步创建一个栈帧用于存储局部变量表,操作数栈,动态连接,方法出口等信息。每个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

本地方法栈

与虚拟机栈类似,不同的是本地方法栈记录的是Native方法。

Java堆

在虚拟机启动时自动创建,存放对象实例。Java世界中“⼏乎”所有的对象都在堆中分配,但是,随着JIT编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致⼀些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。从jdk 1.7开始已经默认开启逃逸分析,如果某些⽅法中的对象引⽤没有被返回或者未被外⾯使⽤(也就是未逃逸出去),那么对象可以直接在栈上分配内存。

方法区

存放已经被虚拟机加载的类型信息,常量,静态变量,及时编译器编译后的代码缓存等数据。在jdk 1.8之前,方法区也叫永久代。

JDK 1.8 的时候,永久代被彻底移除了,取⽽代之是元空间,元空间使⽤的是直接内存。

为什么要用元空间取代方法区?

1.整个永久代有⼀个 JVM 本身设置固定⼤⼩上限,⽆法进⾏调整,⽽元空间使⽤的是直接内存,受本机可⽤内存的限制,虽然元空间仍旧可能溢出,但是⽐原来出现的⼏率会更⼩。
2. 元空间⾥⾯存放的是类的元数据,这样加载多少类的元数据就不由 MaxPermSize 控制了,⽽由系统的实际可⽤空间来控制,这样能加载的类就更多了。
3. 在 JDK8,合并 HotSpot 和 JRockit 的代码时, JRockit 从来没有⼀个叫永久代的东⻄, 合并之后就没有必要额外的设置这么⼀个永久代的地⽅了

运行时常量池

运行时常量池是方法区的一部分。

用来存放编译期生成的各种字面量与符号引用

posted @ 2021-09-06 12:58  刚刚好。  阅读(27)  评论(0编辑  收藏  举报