IT评测·应用市场-qidao123.com技术社区
标题:
JVM 内存结构?
[打印本页]
作者:
万有斥力
时间:
2024-9-23 19:07
标题:
JVM 内存结构?
JVM 内存结构
这里的JVM内存结构,是指
Runtime Data Areas(运行时数据区)
。包含:
方法区(Method Area)
虚拟机栈(VM Stack)
本地方法栈(Native Method)
堆(Heap)
程序计数器(Program Counter Register)
各部分是否私有
通过上图可以知道:
线程私有的部分:
程序计数器
、
本地方法栈
、
虚拟机栈
;
线程间共享的部分:
堆
、
方法区
;
程序计数器
注意:这里的
程序计数寄存器
与
物理中的****CPU的寄存器
是不一样的。
JVM中的PC寄存器是对物理PC寄存器的一种抽象模仿。
程序计数器(Program Counter Register)
是一块较小的内存空间,它可以看作是当前线程所实验的字节码的
行号指示器
。 它是
线程私有的
。
工作细节:
通过改变这个计数器的值来选取下一条必要实验的字节码指令
,
程序控制流,分支、循环、跳转、异常处置惩罚、线程规复等底子功能都必要依靠这个计数器来完成
。
虚拟机栈
虚拟机栈(Java Stack)
,也叫
Java栈
,就是我们平常说的
栈
。
线程私有的
。
除了Native 方法(它通过本地方法栈实现),
其他的 Java 方法调用都是通过栈来实现的
(也必要和其他运行时数据区域好比程序计数器共同)。
每个方法被实验的时间,Java虚拟机都会同步创建一个
栈帧(Stack Frame)
用于
存储局部变量表、利用数栈、动态连接、方法出口等信息
。
局部变量表
:存放局部变量的,以**局部变量槽(Slot)**来表现。
局部变量表的巨细是确定的
,在编译期间完成分配的。
利用数栈
:重要作为方法调用的中转站利用,
用于存放方法实验过程中产生的中间计算结果
。别的,
计算过程中产生的临时变量也会放在利用数栈中
。
动态连接
:用于 一个方法必要调用其他方法的场景。ava 源文件被编译成字节码文件时,变量、方法的引用都是 符号引用(生存在Class 文件的常量池里)。
动态链接 就是在方法调用其他方法时,将 符号引用转换为 直接引用的
。
问:垃圾接纳是否涉及栈内存?
答:不会,由于栈的运行结束后会按从顶至底的序次移除栈对应的线程的方法,所以不必要垃圾接纳机制来处置惩罚长久不用的垃圾。
问:栈内存分配越大越好吗?
答:不是的,我们的物理内存是有限的,如果栈内存分配过大,会导致我们能运行的线程数变少。
可以通过-Xss size(分配的巨细)来指定栈内存的巨细。
问:方法内的 局部变量 是线程安全的吗?
分析:如果它是线程私有的,那肯定是线程安全的。否则就是线程县城不安全的。
答:分环境:
如果这个方法中的局部变量不是static修饰。那就是线程安全的。
①如果这个方法中的局部变量是static修饰。那就是线程不安全的。②如果传入的参数是一个可变对象,并且这个对象在多个线程中被共享和修改,那就可能出现线程安全问题。
本地方法栈
本地方法栈(Native Method Stacks)
与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机 栈为虚拟机实验 Java方法(也就是字节码)服务,而
本地方法栈则是为虚拟机利用到的本地(Native) 方法服务
。
一些带有native
关键字
的方法就是必要JAVA去调用本地的C大概C++方法。
堆
Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建
。此内存区域的唯一目的就是
存放对象实例
,Java 世界里“险些”所有的对象实例都在这里分配内存。
但也不绝对,从 JDK 1.7 开始已经默认开启
逃逸分析
,如果某些方法中的
对象引用没有被返回
大概
未被外面利用(也就是未逃逸出去)
,
那么对象可以直接在栈上分配内存
。
Java 堆区域可细分为:
JDK7 及之前分为:新生代内存(Young Generation)、老生代(Old Generation)、
永久代(Permanent Generation)
;
JDK8 及之后:新生代内存(Young Generation)、老生代(Old Generation);
Metaspace(元空间)
(元空间:利用的是
本地内存
,它只是替换了 永久代 的作用,但**它不属于 堆内存,而是存放于本地内存**)
1、新生代内存(Young Generation):
作用:用于存放
新创建的对象
。大部分对象通常具有
短暂的生命周期
,因此在新生代中频繁进行垃圾接纳,可以高效地接纳大量短生命周期的对象,减少内存占用。
GC接纳:新对象会先被分配到Eden区。当Eden区满了之后触发Minor GC(新生代垃圾接纳)。在接纳过程中,存活下来的对象会被移到其中一个Survivor区;当Survivor区也满了,对象会进一步提拔到老年代。
构成:由年轻区(Eden区)、两个Survivor区(from survivor和to survivor)。默认环境下,新生代的Eden区和Survivor区的空间巨细比例是8:2,可以通过-XX:SurvivorRatio参数调整。
2、老年代:存放颠末多次垃圾接纳仍然存活的对象,大概是大对象(某些JVM可以直接在老年代分配大对象)。老年代中的对象被认为是长时间存活的,因此接纳的频率较低。
大对象:通常指的是必要占用较多连续内存空间的Java对象实例
3、永久代、元空间:(二者作用一样,只是元空间 替换 永久代)
作用:它是具体实现的
方法区
:用来存放类的元数据信息,包括类的结构信息、常量池、静态变量、即时编译后的代码等。
为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢?
重要考虑的是,永久代利用的是JVM内存,因此,当存放的数据太多时,很轻易导致永久代内存溢出(PermGen OutOfMemoryError)。
而元空间利用本地内存而不是 JVM 堆内存,理论上只受限于利用系统的内存巨细。这大大减少了由于类信息、常量等存储导致内存溢出的风险。
方法区
方法区(Method Area)是
线程共享
的。它是Java 虚拟机规范的一个逻辑部分,别名
非堆(Non-Heap)
,目的是与 Java的 堆(Heap)区分开。在不同的虚拟机实现上,方法区的实现是不同的。
方法区重要用于存储已被虚拟机加载的
类信息、常量、静态变量、即时编译器编译后的代码、运行时常量池
。虚拟机启动时就会创建方法区。
JDK中方法区的不同实现
以HotSpot虚拟机来讲,在JDK不同版本汇总,重要关注
字符串常量池位置变迁
:
Jdk1.6及之前: 有永久代,
运行时常量池在永久代,运行时常量池包含字符串常量池
;
Jdk1.7:有永久代,但已经逐步“去永久代”,
字符串常量池从永久代里的运行时常量池分离到堆里
;
Jdk1.8及之后: 无永久代,
运行时常量池在元空间,字符串常量池里依然在堆里
。
问:为什么要将字符串常量池移动到堆中?
答:重要是由于永久代(方法区实现)的 GC 接纳服从太低,只有在整堆收集 (Full GC)的时间才会被实验 GC。Java 程序中通常会有大量的被创建的字符串等待接纳,
将字符串常量池放到堆中,可以或许更高效实时地接纳字符串内存
。
String 类的 intern()方法
参考:https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html
调用字符串对象的intern方法,会将该字符串对象实验放入到
字符串常量池
中:
如果
字符串常量池
中没有该字符串对象,会将该字符串对象复制一份,再放入到
字符串常量池
中;
如果有该字符串对象,则放入失败;
知道了intern()方法的作用,下面来看看String中创建字符串时的区别(以下面的代码示例):
要知道:
直接利用双引号声明出来的String对象会直接存储在字符串常量池中。如:String a = "jack";
利用new创建的String对象,则会在 字符串常量池中创建字符串,并在堆中创建String对象。
public static void main(String[] args) {
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
}
复制代码
JDK1.6 中输出 false、false
由于,JDK1.6中,
字符串常量池
位于 堆的
永久代区域
(我们知道 JVM 堆中的 永久代 是是具体实现的
方法区
),而上图中的 堆(Heap)是特指新生代、老年代。所以:
String s = new String("1");:会在 字符串常量池 中创建字符串"1”,然后在JAVA 堆中创建String对象obj(存储的是 字符串常量池“1”的引用),然后栈中的s指向Java heap中的 obj。
String s2 = "1";是栈中的s2直接去 字符串常量池 中查找是否有“1”,有则直接指向。无则在字符串常量池中创建,然后再指向。
jdk1.7 中输出 false、true
jdk1.7中,字符串常量池 从永久代 移动到正常的 Java 堆(中的 年轻代、老年代)中了。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/)
Powered by Discuz! X3.4