大家好,又见面了,我是你们的朋友全栈君。
近期在学习研究内存,那么Jvm内存结构和Jvm的内存模型即JMM(Java momery model)这两项内容都是学习java虚拟机、java内存知识的基础。为了让自己加深理解,有不至于嵌入到底层细节太深,会通过一段代码片段类比到内存结构图中的真实呈现。
JVM运行数据区,也就是我们所说的内存结构主要分为两个大区:
1、线程共享区
**方法区(Method Area)😗*存储运行时的常量池、被虚拟机加载过的类信息、常量、静态变量、即时编译器编译后的代码数据。
**堆区(Heap Area)😗*所有的对象实例以及数组都要在堆上分配,也是垃圾回收器主要管理的对象。
2、线程独占区
**虚拟机栈:**又称Java栈,存储局部变量表、操作栈、动态链接、方法出口,对象指针。
**本地方法栈:**为虚拟机使用到的Native 方法服务。如Java使用c或者c++编写的接口服务时,代码在此区运行,Android中的Jni本地方法调用亦该如此。
**程序计数器:**当前线程执行的字节码的行号指示器。
接下来我们通过一段简单的代码来看实际内存结构图
先看实例代码:
public class MemoryStructure {
static int sSize =10;//静态变量 方法区
static MemoryObj memoryObj=new MemoryObj(sSize);//声明部分(静态类变量)放在方法区,对象实例在堆中
int initSize=20;//类的成员变量 堆区
MemoryObj memoryObj2=new MemoryObj(initSize);//声明部分(引用类型成员变量),实例都在 堆中
public static void main(String[] args) {
//MemoryStructure memoryStructure 声明部分(引用类型) 放在虚拟栈
MemoryStructure memoryStructure = new MemoryStructure();
int size3=30;//栈区
//MemoryObj memoryObj3声明部分(引用类型) 放在虚拟栈
MemoryObj memoryObj3= new MemoryObj(size3);
//新开线程 :新的独享虚拟栈
new Thread(){
@Override
public void run() {
int k=40;//栈区
setSize(40);
}
void setSize(int size){
memoryStructure.memoryObj2.size=size;
//说明:
//新线程访问主线程的局部变量是无法访问的,当前编译器没有报错,是因为idea工具编译做了处理
//查看一下编译后的字节码: final MemoryObj memoryObj3 = new MemoryObj(size3);
MemoryObj temp=memoryObj3;
}
}.start();
}
}
class MemoryObj{
int size;
public MemoryObj(int size) {
this.size = size;
}
}
上述代码,对照内存结构图的分布位置如下:
正如代码中的注释和上述代码片段在各区中的分布图,能很清晰的知晓Jvm的内存结构。
补充一些堆和方法区的理解,虽然Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java 堆区分开来。
方法区是为类信息服务的,存储类信息、常量、静态变量。成员变量直接存在在堆中。
虚拟栈区可以理解成为程序的执行服务的,方法中定义的局部变量,被保存在这个位置,最终方法的执行是通过出栈压栈的方式执行。
方法区、堆区是共享区域;虚拟栈区是独享区域:
每一个线程都会对应一个虚拟栈(又称java栈),上述newThread中的MemoryObj temp=memoryObj3;,若memoryObj3是无final修饰,是无法直接访问的,栈内数据是独享的。
这篇是通过一个实例分析的方式,对jvm的内存结构有了更清晰的认识。如若想做更深度的了解,推荐《深入理解 Java 虚拟机》这本书籍。 发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/140576.html原文链接:https://javaforall.cn