JVM 内部使用的 Java 内存模型, 在逻辑上将内存划分为 线程栈
(thread stacks)和堆内存
(heap)两个部分。 如下图所示:
JVM 中,每个正在运行的线程,都有自己的线程栈。 线程栈包含了当前正在执行的方法链/调用链上的所有方法的状态信息。
原始数据类型和对象引用地址在栈上;对象、对象成员与类定义、静态变量在堆上。
堆内存又称为“共享堆
”,堆中的所有对象,可以被所有线程访问, 只要他们能拿到对象的引用地址。
- 如果一个线程可以访问某个对象时,也就可以访问该对象的成员变量。
- 如果两个线程同时调用某个对象的同一方法,则它们都可以访问到这个对象的成员变量,但每个线程的局部变量副本是独立的。
JVM 将 Heap 内存分为年轻代(Young generation)和老年代(Old generation, 也叫 Tenured)两部分。
年轻代还划分为 3 个内存池,新生代(Eden space)和存活区(Survivor space), 在大部分 GC 算法中有 2 个存活区(S0, S1),在我们可以观察到的任何时刻,S0 和 S1 总有一个是空的, 但一般较小,也不浪费多少空间。
具体实现对新生代还有优化,那就是 TLAB(Thread Local Allocation Buffer), 给每个线程先划定一小片空间,你创建的对象先在这里分配,满了再换。这能极大降低并发资源锁定的开销。
Non-Heap 本质上还是 Heap,只是一般不归 GC 管理,里面划分为 3 个内存池。
- Metaspace, 以前叫持久代(永久代, Permanent generation), Java8 换了个名字叫 Metaspace. Java8 将方法区移动到了 Meta 区里面,而方法又是class的一部分和 CCS 交叉了?
- CCS, Compressed Class Space, 存放 class 信息的,和 Metaspace 有交叉。
- Code Cache, 存放 JIT 编译器编译后的本地机器代码。
- CPU 有一个性能提升的利器:
指令重排序
; - JMM 规范对应的是 JSR133, 现在由 Java 语言规范和 JVM 规范来维护;
- 内存屏障的分类与作用
CPU会在合适的时机,按需要对将要进行的操作重新排序,但是有时候这个重排机会导致我们的代码跟预期不一致。文章来源:https://www.toymoban.com/news/detail-439729.html
怎么办呢?JMM 引入了内存屏障机制。文章来源地址https://www.toymoban.com/news/detail-439729.html
到了这里,关于Java 内存模型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!