jvm内存模型(代码片段)

beilou310 beilou310     2023-02-01     457

关键词:

开始学Java的时候,听到好多都说Java编程不用考虑内存管理,比C方便多了。但是后来看一些基础知识,发现不了解Java各个部分内存分布,有些概念很难理解。

JVM内存分为5个部分:方法区,JVM堆,JVM栈,本地方法栈,程序计数器。

程序计数器:线程私有,用于记录当前线程执行的位置。用于切换回来之时的程序入口。

本地方法栈:线程私有,用于本地native方法运行,本地方法被执行的时候,在本地方法栈会创建一个栈帧,用于存放本地方法的局部变量表、操作数栈、动态链接、出口信息。

JVM栈:线程私有,它的生命周期与线程相同。描述的是java方法执行的内存模型:每个方法在执行的同时创建一个栈帧,用于存放局部变量表,操作数栈,方法入口,动态链接

             等。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在 虚拟机栈中从入栈到出栈的过程。

             局部变量表用来存放一些基本数据类,和引用。操作数栈的话,是用来作运算用的。

             局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用和returnAddress 类型。局部变量表所需的内存空间在

                 编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

JVM堆:线程共享,在虚拟机启动时创建。存放对象实例,几乎所有的对象实例都在这里分配内存。所有的对象实例以及数组都要在堆上分配。Java垃圾回收也主要是指处理堆。

方法区线程共享,它用于存 储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

                 方法区中的信息一般需要长期存在,回收一遍内存之后可能只有少量垃圾。对方法区的内存回收的主要目标是:对常量池的回收 和 对类型的卸载。

 运行时常量池:(Runtime Constant Pool)是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant PoolTable),

                                  用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中

 技术分享图片

 

技术分享图片

 

Object obj = new Object();假设这句代码出现在方法体中,那“Object obj”这部分的语义将会反映到Java 栈的本地变量表中,作为一个reference 类型数据出现。而“new Object()”这部分的语义将会反映到Java 堆中,形成一块存储了Object 类型所有实例数据值(Instance Data,对象中各个实例字段的数据)的结构化内存,根据具体类型以及虚拟机实现的对象内存布

局(Object Memory Layout)的不同,这块内存的长度是不固定的。

 

由于reference 类型在Java 虚拟机规范里面只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位,以及访问到Java 堆中的对象的具体位置,因此

不同虚拟机实现的对象访问方式会有所不同,主流的访问方式有两种:使用句柄和直接指针。具体可以参考博文:https://www.cnblogs.com/dingyingsi/p/3760447.html

相当于是堆内部结构不同的划分。

 

堆区: 

1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) 
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 
栈区: 
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中 
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问

下面举一个例子:

 

 1 package lesson;
 2 
 3 public class JVMDemo //运行时, jvm 把JVMDemo的信息都放入方法区
 4     private static int n = 0;  //static静态变量存入方法区
 5     private final int m=1;     //final常量存入方法区
 6 
 7     public static void main(String[] args)    //main 方法本身放入方法区。
 8         
 9         Test test = new Test("Test 1");//test是引用,所以放到栈区里, Test是自定义对象应该放到堆里面
10         Test test1 = new Test("Test 2");
11         test.printname();
12         test1.printname();
13     
14 
15 
16 class Test//运行时, jvm 把Test的信息都放入方法区
17     private String name;  //new Test实例后, name 引用放入栈区里,  name 对象放入堆里
18 
19     public Test(String name) 
20         super();
21         this.name = name;
22     
23     
24     public void printname() //printname方法本身放入 方法区里。
25         System.out.println("name is "+ this.name);        
26         
27 

 

启动了一个Java虚拟机进程,这个进程首先从classpath中找到JVMDemo.class文件,读取这个文件中的二进制数据,然后把Appmain类的类信息存放到运行时数据区的方法区中。这一过程称为AppMain类的加载过程。接着,Java虚拟机定位到方法区中JVMDemo类的Main()方法的字节码,开始执行它的指令。这个main()方法的第一条语句就是:
Test test=new Test("测试1");

让java虚拟机创建一个Sample实例,并且呢,使引用变量test1引用这个实例。让我们来跟踪一下Java虚拟机,看看它究竟是怎么来执行这个任务的:
1、 Java虚拟机一看,不就是建立一个Test实例吗,简单,于是就直奔方法区而去,先找到Test类的类型信息再说。但是方法区里还没有Test类呢。可Java虚拟机也不是一根筋的笨蛋,于是,立马加载了Sample类,把Sample类的类型信息存放在方法区里。
2、 信息找到了。Java虚拟机做的第一件事情就是在堆区中为一个新的Test实例分配内存, 这个Test实例持有着指向方法区的Test类的类型信息的引用。这里所说的引用,实际上指的是Test类的类型信息在方法区中的内存地址,而这个地址呢,就存放了在Test实例的数据区里。
3、 在JAVA虚拟机进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。OK,原理讲完了,就让我们来继续我们的跟踪行动!位于“=”前的test是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方法调用栈中。而“=”将把这个test变量指向堆区中的Test实例,也就是说,它持有指向Test实例的引用。
接下来,JAVA虚拟机将继续执行后续指令,在堆区里继续创建另一个Test实例,然后依次执行它们的printname()方法。当JAVA虚拟机执行test1.printName()方法时,JAVA虚拟机根据局部变量test1持有的引用,定位到堆区中的Test实例,再根据Test实例持有的引用,定位到方法去中Sample类的类型信息,从而获得printname()方法的字节码,接着执行printname()方法包含的指令。

上面这部分参考https://www.cnblogs.com/dingyingsi/p/3760730.html

通过上面的了解,应该知道整个程序是在JVM中如何分配内存的了,也大概知道程序是跑在哪一块了。如果理解有错误请指正。

 











[转帖]jvm内存结构vsjava内存模型vsjava对象模型(代码片段)

JVM内存结构VSJava内存模型VSJava对象模型https://www.hollischuang.com/archives/2509 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如... 查看详情

jvm内存模型(代码片段)

开始学Java的时候,听到好多都说Java编程不用考虑内存管理,比C方便多了。但是后来看一些基础知识,发现不了解Java各个部分内存分布,有些概念很难理解。JVM内存分为5个部分:方法区,JVM堆,JVM栈,本地方法栈,程序计数器... 查看详情

jvm内存模型(代码片段)

jvm内存结构回顾:1.程序计数器程序计数器(ProgramCounterRegister)是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的每条线程拥有一... 查看详情

jvm内存模型(代码片段)

...u010425776/article/details/51170118Java虚拟机(JavaVirtualMachine=JVM)的内存空间分为五个部分,分别是:1.程序计数器2.Java虚拟机栈3.本地方法栈4.堆5.方法区。下面对这五个区域展开深入的介绍。1.程序计数器1.1.什么是程序计数器?程序计数... 查看详情

jvm虚拟机内存模型(代码片段)

来源:https://blog.csdn.net/A_zhenzhen/article/details/77917991?locationNum=8&fps=1    https://blog.csdn.net/hxpjava1/article/details/55189077概述  java的内存管理采用自动内存管理机制,这样就不需要程序员去写释放内存的代码,而且不容 查看详情

浅谈jvm内存结构,java内存模型和java对象模型(代码片段)

Java虚拟机正文开始@Assassin目录Java虚拟机1.JVM内存结构:1.1Java虚拟机栈:1.2堆:1.3方法区:2.Java内存模型:3.Java对象模型:4.三者区别:1.JVM内存结构:Java代码是要运行在Java虚拟机上的,而虚拟机在执行Java程序的过程中会... 查看详情

jvm内存模型(代码片段)

...lMachine,简称JVM)在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束... 查看详情

jvm内存模型的那些事(代码片段)

  阅读相关资料,自己先画了一个jvm内存模型草图       类装在子系统不过多解释,上一篇类加载机制说的就是这个。  字节码执行引擎(执行编译好后class文件指令码的程序),为C语音实现,不可见,... 查看详情

jvm-内存模型(代码片段)

...程同步控制,而函数内变量不用?5. JVM什么时候会做内存回收,怎么 查看详情

jvm内存结构java内存模型和java对象模型(代码片段)

Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文要讨论的JVM内存结构、Java内存模型和Java对象模型,这就是三个截然不同... 查看详情

jvm_12jmm内存模型(代码片段)

学习视频链接:黑马程序员JVM完整教程1.java内存模型(JMM)JMM即JavaMemoryModel,它定义了主存(共享内存)、工作内存(线程私有)抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。JMM体... 查看详情

克服焦虑--图解jvm内存模型和jvm线程模型(代码片段)

...f0c;我正在创作Java多线程系列文章,严格的说,JVM内存模型的知识并不隶属于Java多线程范畴,但在讨论多线程的过程中,会涉及到相关概念,考虑到它作为面经常客,故单独成篇进行知识梳理。在各种有意... 查看详情

克服焦虑--图解jvm内存模型和jvm线程模型(代码片段)

...f0c;我正在创作Java多线程系列文章,严格的说,JVM内存模型的知识并不隶属于Java多线程范畴,但在讨论多线程的过程中,会涉及到相关概念,考虑到它作为面经常客,故单独成篇进行知识梳理。在各种有意... 查看详情

jvm系列之jmm内存模型(代码片段)

java内存划分JMM规定了内存主要划分为主内存和工作内存两种。此处的主内存和工作内存跟JVM内存划分(堆、栈、方法区)是在不同的层次上进行的,如果非要对应起来,主内存对应的是Java堆中的对象实例部分ÿ... 查看详情

深入理解jvm:内存结构垃圾回收类加载内存模型(代码片段)

文章目录内存结构1.本地方法栈(NativeMethodStack)2.程序计数器(ProgramCounterRegiste)3.虚拟机栈(JavaVirtualMachineStacks)4.堆(Heap)5.方法区(MethodArea)垃圾回收 查看详情

day797.jvm内存模型-java性能调优实战(代码片段)

JVM内存模型Hi,我是阿昌,今天学习记录的是关于JVM内存模型。JVM算是面试中的高频问题了,通常情况下总会有人问到:请讲解下JVM的内存模型,JVM的性能调优做过吗?一、为什么JVM在Java中如此重要?... 查看详情

jvm内存模型与gc算法(简介)(代码片段)

 JVM内存模型如上图,需要声明一点,这是《Java虚拟机规范(JavaSE7版)》规定的内容,实际区域由各JVM自己实现,所以可能略有不同。以下对各区域进行简短说明。1.1程序计数器 程序计数器是众多编程语言都共有的一部... 查看详情

jvm--内存模型与线程(代码片段)

...算速度存在几个数量级的差距,现在计算机系统不得不在内存和处理器之间增加一层高速缓存(cache)来作为缓冲。将运算需要的数据复制到缓存中,让运算能够快速进行,当运算结束的时候再讲数据从缓存同步到内存中,这样处... 查看详情