java内存模型(一)
发布日期:2021-06-28 18:55:03 浏览次数:3 分类:技术文章

本文共 1352 字,大约阅读时间需要 4 分钟。

在提到java的内存模型是,一般都会说堆栈、程序计数器、方法区等这些设计。这里我更觉得秦大哥的说明更加容易理解。那么接下来我会根据秦大哥的解释进行总结说明。

 

一、内存结构:

内存结构通常说的就是栈、堆这些结构。从逻辑结构上分为线程栈、堆内存、非堆内存。

  • 线程栈:为什么叫线程栈呢?因为首先这部分的数据结构是栈。每个线程都会有自己栈。JVM为每个新创建的线程都分配一个堆栈。线程栈包含了当前正在执行的方法链/调用链上的所有方法的状态信息。线程栈中保存了方法内的局部变量。线程栈有如下特点:
    • 每个线程都只能访问自己的线程栈
    • 每个线程都不能访问(看不见)其他线程的局部变量
    • 所有原生类型的局部变量都存储在线程栈中,因此对其他线程是不可见的
    • 线程可以将一个原生变量值的副本传给另一个线程,但不能共享原生局部变量本身
    • 堆内存中包含了Java代码中创建的所有对象,不管是哪个线程创建的。 其中也涵盖了包装类型(例如 Byte , Integer , Long 等)
    • 不管是创建一个对象并将其赋值给局部变量, 还是赋值给另一个对象的成员变量, 创建的对象都会被保存到堆内存中
    • 对象的成员变量与对象本身一起存储在堆上, 不管成员变量的类型是原生数值,还是对象引用 
    • 类的静态变量则和类定义一样都保存在堆中
    • 栈帧:栈帧是一个逻辑上的概念,具体的大小在一个方法编写完成后基本上就能确定。线程执行过程中,一般会有多个方法组成调用栈(Stack Trace), 比如A调用B,B调用C。。。每执行到一个方法,就会创建对应的 栈帧(Frame)。

       

 

  • 堆:堆内存又称为“ 共享堆 ”,堆中的所有对象,可以被所有线程访问, 只要他们能拿到对象的引用地址。堆结构的特点如下:
    • 如果一个线程可以访问某个对象时,也就可以访问该对象的成员变量
    • 如果两个线程同时调用某个对象的同一方法,则它们都可以访问到这个对象的成员变量,但每个线程的局部变量副本是独立的
    • 堆通常分为:年轻代(Young generation)和老年代(Old generation,也叫 Tenured)两部分。
    • 年轻代还划分为3个内存池,新生代(Eden space)和存活区(Survivor space), 在大部分GC算法中有2个存活区(S0, S1),在我们可以观察到的任何时刻,S0和S1总有一个是空的。
    • JVM对新生代还有优化,那就是TLAB(Thread Local Allocation Buffer), 给每个线程先划定一小片空间,你创建的对象先在这里分配,满了再换。这能极大降低并发资源锁定的开销。
  • 非堆:不归GC管理,里面划分为3个内存池:
    • Metaspace,以前叫持久代(永久代, Permanent generation), Java8换了个名字叫Metaspace
    • CCS,Compressed Class Space,存放class信息的,和Metaspace有交叉
    • Code Cache, 存放 JIT 编译器编译后的本地机器代码
  • 程序计数器:当前线程执行到哪一行字节码指令,这个信息则被存放在程序计数寄存器。每个线程拥有自己独立的程序计数器。此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

转载地址:https://blog.csdn.net/xt00002003/article/details/115363822 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java内存模型(二)
下一篇:JVM 类加载器

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月14日 15时28分39秒