前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >JVM内存—堆(heap)栈(stack)方法区(method) (转)

JVM内存—堆(heap)栈(stack)方法区(method) (转)

作者头像
翎野君
发布于 2023-05-12 07:53:42
发布于 2023-05-12 07:53:42
47900
代码可运行
举报
文章被收录于专栏:翎野君翎野君
运行总次数:0
代码可运行

JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)

堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令) 2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 栈区: 1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中 2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。 3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。 方法区: 1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量及常量。 2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。 为了更清楚地搞明白发生在运行时数据区里的黑幕,我们来准备2个小道具(2个非常简单的小程序)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
AppMain.java

 public   class  AppMain                

//运行时, jvm 把appmain的信息都放入方法区

{

public   static   void  main(String[] args)  //main 方法本身放入方法区。

{

Sample test1 = new  Sample( " 测试1 " );   //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面

Sample test2 = new  Sample( " 测试2 " );

test1.printName();

test2.printName();

}

} 
Sample.java

 public   class  Sample        //运行时, jvm 把appmain的信息都放入方法区

{

/** 范例名称 */

private  name;      //new Sample实例后, name 引用放入栈区里,  name 对象放入堆里

/** 构造方法 */

public  Sample(String name)

{

this .name = name;

}

/** 输出 */

public   void  printName()   //print方法本身放入 方法区里。

{

System.out.println(name);

}

} 

【javac AppMain.java】将我们编写的java类转换成计算机jvm可识别的二进制的class文件

【java AppMain】注意执行的时候java命令后面不需要加.class

执行命令后:

1.启动了一个Java虚拟机进程,这个进程首先从classpath中找到AppMain.class文件,读取这个文件中的二进制数据,然后把Appmain类的类信息存放到运行时数据区的方法区中。

   这一过程称为AppMain类的加载过程。

2.Java虚拟机定位到方法区中AppMain类的main()方法的字节码,开始执行它的指令。这个main()方法的第一条语句就是:Sample test1=new Sample("测试1");

要求java虚拟机创建一个Sample实例,并且呢,使引用变量test1引用这个实例。

3.Java虚拟机一看,不就是建立一个Sample实例吗,简单,于是就直奔方法区而去,先找到Sample类的类型信息再说。结果呢,嘿嘿,没找到,这会儿的方法区里只有AppMain类但是还没有Sample类。可Java虚拟机也不是一根筋的笨蛋,于是,它发扬“自己动手,丰衣足食”的作风,立马加载了Sample类,把Sample类的类型信息存放在方法区里。

4.Java虚拟机做的第一件事情就是在堆区中为一个新的Sample实例分配内存, 这个Sample实例(指的是在堆中刚刚被分配了内存的实例)持有着指向方法区的Sample类的类型信息的引用。这里所说的引用,实际上指的是Sample类的类型信息在方法区中的内存地址,其实,就是有点类似于C语言里的指针啦~~,而这个地址呢,就存放了在Sample实例的数据区里。

5、 在JAVA虚拟机进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。OK,原理讲完了,就让我们来继续我们的跟踪行动!位于“=”前的test1是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方法调用栈中。而“=”将把这个test1变量指向堆区中的Sample实例,也就是说,它持有指向Sample实例的引用

6.接下来,JAVA虚拟机将继续执行后续指令,在堆区里继续创建另一个Sample实例,然后依次执行它们的printName()方法。当JAVA虚拟机执行test1.printName()方法时,JAVA虚拟机根据局部变量test1持有的引用,定位到堆区中的Sample实例,再根据Sample实例持有的引用,定位到方法去中Sample类的类型信息,从而获得printName()方法的字节码,接着执行printName()方法包含的指令(按照上图箭头进行回溯理解

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
内存分区&&C++之引用的深度剖析
阑梦清川
2025/02/24
690
内存分区&&C++之引用的深度剖析
C++内存分区模型分析与实例以及扩展
不要返回局部变量的地址,栈区开辟的数据由编译器自动释放,函数运行结束后函数内的局部变量被释放,将无法使用传回的函数体内的局部变量的地址!
CtrlX
2022/08/04
8120
C++内存分区模型分析与实例以及扩展
c++之内存模型
堆区:由程序员分配释放,若程序员不释放,则程序结束时由系统释放。在c++中主要利用new在堆区开辟内存。
西西嘛呦
2020/08/26
7160
C++核心编程(上)
结论:C++推荐用引用技术,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了
C语言与CPP编程
2020/12/02
1.9K0
c++ 内存分区模型
放在int main外面和函数外面的变量叫做全局变量 , 在int main 中或者函数中的变量叫做普通局部变量 ,在普通变量前边加上一个static的叫做静态变量 , 也放在全局区域中
青衫哥
2023/03/31
2520
c++ 内存分区模型
C++ 中堆区内存与栈区内存相互赋值的一些思考
堆区的数据对象与栈区的变量是可以相互赋值的。 堆区内存由编译器自动分配释放 ,存放函数的参数值,局部变量的值等,内存的分配是连续的,当声明变量时,那么编译器会自动接着当前栈区的结尾来分配内存。堆区内存由程序员分配释放, 若程序员不释放,程序结束时可能由操作系统回收。类似于链表,在内存中的分布不是连续的,它们是不同区域的内存块通过指针链接起来的。两种类型的内存地址相互赋值的本质是改变了变量的内存地址的指向。
耕耘实录
2022/05/09
5130
内存、引用、封装、函数
内存内存分区模型代码区:存放函数体的二进制代码,由操作系统进行管理全局区:存放全局变量、静态变量和常量栈区:由编译器自动分配释放,存放函数的参数值、局部变量等堆区:由程序员分配释放,若程序员不释放,程序结束时由操作系统回收内存分区意义:不同分区存放的数据,赋予不同的生命周期,灵活编程程序运行前程序编译后,生成.exe可执行程序,未执行该程序前,分为两个区域:代码区:存放CPU执行的机器指令代码区是共享的,目的是对于频繁被执行的程序,只需要在内存中有一份代码即可代码区是只读的,防止程序意外的修改了它的指令全局
WuShF
2023/02/25
7870
内存、引用、封装、函数
C++中指针与引用详解
在计算机存储数据时必须要知道三个基本要素:信息存储在何处?存储的值为多少?存储的值是什么类型?因此指针是表示信息在内存中存储地址的一类特殊变量,指针和其所指向的变量就像是一个硬币的两面。指针一直都是学习C语言的难点,在C++中又多了一个引用的概念。初学时很容易把这两个概念弄混,下面就来通过一些例子来说明二者之间的差别。
呆呆
2021/07/05
7470
day9嵌入式(2022.1.15)
===================== 1.程序文件分析 ==========================
天天Lotay
2022/12/02
3660
day9嵌入式(2022.1.15)
看完这篇你还能不懂C语言/C++内存管理?
C 语言内存管理指对系统内存的分配、创建、使用这一系列操作。在内存管理中,由于是操作系统内存,使用不当会造成毕竟麻烦的结果。本文将从系统内存的分配、创建出发,并且使用例子来举例说明内存管理不当会出现的情况及解决办法。
C语言与CPP编程
2020/12/02
5890
看完这篇你还能不懂C语言/C++内存管理?
【C/C++】——小白初步了解——内存管理
特点:如果新大小大于原大小,新分配的内存区域中的内容是不确定的;如果新大小小于原大小,超出的内容将被丢弃。
小李很执着
2024/06/15
1360
C语言内存讲解-详说内存分布和heap空间
程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、数据区(data)和未初始化数据区(bss)3 个部分(有些人直接把data和bss合起来叫做静态区或全局区)。
莫浅子
2022/11/18
6050
C语言内存讲解-详说内存分布和heap空间
编码篇-iOS程序中的内存分配 栈区堆区全局区等相关知识
在计算机的系统中,运行的应用程序中的数据都是保存在内存中,不同类型的数据,保存的内存区域不同。内存区域大致可以分为:栈区、堆区、全局区(静态区)、文字常量区、程序代码区。学习内存相关的知识对我们的日常开发是十分必要的。
進无尽
2018/09/12
1.6K0
编码篇-iOS程序中的内存分配 栈区堆区全局区等相关知识
堆和栈
程序在系统上运行时,会为程序分配内存,有堆区 栈区 全局区 代码区 我们主要介绍堆区和栈区
用户7272142
2023/10/11
1450
堆和栈
详解栈区、堆区、全局区、文字常量区、程序代码区
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,再根据edx读取字符,显然慢了。
xy_ss
2023/11/22
4580
黑马程序员c++课件_黑马java课程大纲
配套视频: https://www.bilibili.com/video/BV1et411b73Z 只是为方便学习,不做其他用途,在此发布C++基础入门部分配套讲义,原作者为黑马程序
全栈程序员站长
2022/11/04
1.9K0
刷了这么多题,你了解自己代码的内存消耗么?
例如Python万物皆对象,并且将内存操作封装的很好,所以python的基本数据类型所用的内存会要远大于存放纯数据类型所占的内存,例如,我们都知道存储int型数据需要四个字节,但是使用Python 申请一个对象来存放数据的话,所用空间要远大于四个字节。
代码随想录
2021/04/07
4640
刷了这么多题,你了解自己代码的内存消耗么?
局部变量,静态局部变量,全局变量,静态全局变量在内存中的存放区别(转)
     我们先来看内存中的几大区:  内存到底分几个区? 下面有几种网上的理解,我整理一下: 一:  1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。  2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由os回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。  3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的
Linux云计算网络
2018/01/10
6K0
写了这么多代码,你了解自己代码的内存消耗么?
例如Python万物皆对象,并且将内存操作封装的很好,所以python的基本数据类型所用的内存会要远大于存放纯数据类型所占的内存,例如,我们都知道存储int型数据需要四个字节,但是使用Python 申请一个对象来存放数据的话,所用空间要远大于四个字节。
PHP开发工程师
2021/05/08
6310
写了这么多代码,你了解自己代码的内存消耗么?
C++核心编程笔记合集
​ 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
CtrlX
2023/03/21
1K0
C++核心编程笔记合集
推荐阅读
相关推荐
内存分区&&C++之引用的深度剖析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验