文档章节

深入Java虚拟机:JVM中的Stack和Heap

~少司命~
 ~少司命~
发布于 2013/02/19 11:09
字数 1547
阅读 63
收藏 2

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>


在JVM中,静态属性保存在Stack指令内存区,动态属性保存在Heap数据内存区。本文将从JVM的角度来讲解Java虚拟机的这一机制。

AD:2013大数据全球技术峰会低价抢票中

在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题。

一般,JVM的内存分为两部分:Stack和Heap。

Stack(栈)是JVM的内存指令区。Stack管理很简单,push一定长度字节的数据或者指 令,Stack指针压栈相应的字节位移;pop一定字节长度数据或者指令,Stack指针弹栈。Stack的速度很快,管理很简单,并且每次操作的数据或 者指令字节长度是已知的。所以Java 基本数据类型,Java 指令代码,常量都保存在Stack中。

Heap(堆)是JVM的内存数据区。Heap 的管理很复杂,每次分配不定长的内存空间,专门用来保存对象的实例。在Heap 中分配一定的内存来保存对象实例,实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在 Stack中),在Heap 中分配一定的内存保存对象实例和对象的序列化比较类似。而对象实例在Heap 中分配好以后,需要在Stack中保存一个4字节的Heap 内存地址,用来定位该对象实例在Heap 中的位置,便于找到该对象实例。

由于Stack的内存管理是顺序分配的,而且定长,不存在内存回收问题;而Heap 则是随机分配内存,不定长度,存在内存分配和回收的问题;因此在JVM中另有一个GC进程,定期扫描Heap ,它根据Stack中保存的4字节对象地址扫描Heap ,定位Heap 中这些对象,进行一些优化(例如合并空闲内存块什么的),并且假设Heap 中没有扫描到的区域都是空闲的,统统refresh(实际上是把Stack中丢失了对象地址的无用对象清除了),这就是垃圾收集的过程;关于垃圾收集的更 深入讲解请参考51CTO之前的文章《JVM内存模型及垃圾收集策略解析》。

JVM的体系结构 
JVM的体系结构

我们首先要搞清楚的是什么是数据以及什么是指令。然后要搞清楚对象的方法和对象的属性分别保存在哪里。

1)方法本身是指令的操作码部分,保存在Stack中;

2)方法内部变量作为指令的操作数部分,跟在指令的操作码之后,保存在Stack中(实际上是简单类型保存在Stack中,对象类型在Stack中保存地址,在Heap 中保存值);上述的指令操作码和指令操作数构成了完整的Java 指令。

3)对象实例包括其属性值作为数据,保存在数据区Heap 中。

非静态的对象属性作为对象实例的一部分保存在Heap 中,而对象实例必须通过Stack中保存的地址指针才能访问到。因此能否访问到对象实例以及它的非静态属性值完全取决于能否获得对象实例在Stack中的地址指针。

非静态方法和静态方法的区别:

非静态方法有一个和静态方法很重大的不同:非静态方法有一个隐含的传入参数,该参数是JVM给它的,和我们怎么 写代码无关,这个隐含的参数就是对象实例在Stack中的地址指针。因此非静态方法(在Stack中的指令代码)总是可以找到自己的专用数据(在Heap 中的对象属性值)。当然非静态方法也必须获得该隐含参数,因此非静态方法在调用前,必须先new一个对象实例,获得Stack中的地址指针,否则JVM将 无法将隐含参数传给非静态方法。

静态方法无此隐含参数,因此也不需要new对象,只要class文件被ClassLoader load进入JVM的Stack,该静态方法即可被调用。当然此时静态方法是存取不到Heap 中的对象属性的。

总结一下该过程:当一个class文件被ClassLoader load进入JVM后,方法指令保存在Stack中,此时Heap 区没有数据。然后程序技术器开始执行指令,如果是静态方法,直接依次执行指令代码,当然此时指令代码是不能访问Heap 数据区的;如果是非静态方法,由于隐含参数没有值,会报错。因此在非静态方法执行前,要先new对象,在Heap 中分配数据,并把Stack中的地址指针交给非静态方法,这样程序技术器依次执行指令,而指令代码此时能够访问到Heap 数据区了。

静态属性和动态属性

前面提到对象实例以及动态属性都是保存在Heap 中的,而Heap 必须通过Stack中的地址指针才能够被指令(类的方法)访问到。因此可以推断出:静态属性是保存在Stack中的,而不同于动态属性保存在Heap 中。正因为都是在Stack中,而Stack中指令和数据都是定长的,因此很容易算出偏移量,也因此不管什么指令(类的方法),都可以访问到类的静态属 性。也正因为静态属性被保存在Stack中,所以具有了全局属性。

在JVM中,静态属性保存在Stack指令内存区,动态属性保存在Heap数据内存区。

本文转载自:http://developer.51cto.com/art/201003/188753.htm

~少司命~
粉丝 3
博文 76
码字总数 8735
作品 0
昌平
高级程序员
私信 提问
加载中

评论(1)

阳光test
阳光test
写的不错,学习了!
JVM 深入笔记(2)内存溢出场景模拟

JVM 深入笔记(2)各内存区溢出场景模拟 作者:柳大 · Poechant 电邮:zhongchao.ustc#gmail.com (#->@) 博客:blog.csdn.net/poechant 日期:Feb. 23st 2012 《JVM 深入笔记(1)内存区域是...

晨曦之光
2012/04/24
185
0
01 深入理解JVM的内存区域

先来看看JVM运行时候的内存区域,如下图:   大多数 JVM 将内存区域划分为 Heap(堆)、方法区、Stack(栈)、本地方法栈、程序计数器。其中 Heap 和 方法区 是线程共享的,Stack、本地方法...

osc_ma60u6gg
2018/02/28
2
0
《深入理解Java虚拟机》摘抄(1-3章)

通常情况下JDK包含了JRE。 JVM在JRE中。 JDK结构体系图 图片来源:https://docs.oracle.com/javase/8/docs/ Java的优点 OpenJDK 与 Oracle JDK 查看安装的是oracleJDK还是openJDK openJDK则显...

FutaoSmile丶
2019/04/02
0
0
Java虚拟机运行时数据区结构

本文部分参考自《Java虚拟机规范(Java SE 7版)》的中译本和周志明的《深入理解Java虚拟机》,另加个人理解。原书对Java虚拟机运行时数据区描述只有6页,同时参考其他网络网资料,个人能力所...

foodon
2014/12/09
384
4
hello world 执行原理

1 public class HelloWorld {2 public static void main(String[] args)3 { 4 String s ;5 s = “Hello World!”; //定义字符串s6 System.out.println(s);7 }8 } ↑↑↑是一个简单的java程序......

osc_02hzs6k2
2019/07/05
2
0

没有更多内容

加载失败,请刷新页面

加载更多

kafka重要概念与集群重点配置详解

重要概念 broker 一个broker就是一个kafka实例,负责接收、转发、存储消息,kafka集群就是由多个broker组成。 topic kafka的topic是一个逻辑概念,就是对消息分组、分类,便于区分处理不同业...

trayvon
31分钟前
42
0
在树莓派里搭建 Lighttpd 服务器

Lighttpd 像 Ngnix 一样,是被设计运行在低内存,低 CPU 负载的设备上,它们都非常适合在树莓派上运行。 本文将介绍如何在树莓派上运行基本配置的 Lighttpd ,以及如何与 PHP-FRM 一起使用。...

良许Linux
31分钟前
10
0
Service Mesh 高可用在企业级生产中的实践 | 线上直播回顾

Service Mesh Virtual Meetup 是 ServiceMesher 社区和 CNCF 联合主办的线上系列直播。本期为 Service Mesh Virtual Meetup#1 ,邀请了四位来自不同公司的嘉宾,从不同角度展开了 Service Me...

SOFAStack
40分钟前
34
0
word转pdf软件有哪些?word转pdf软件怎么操作?

虽说日常生活中,很多人写报告写策划都依然会使用word程序,但是严格来说,word却并非是唯一常用的办公软件,就比如说pdf,就越来越受年轻人的欢迎了,那么经常用电脑办公的你是否知道,其实...

开源86
54分钟前
39
0
Java创建对象的过程(类实例化)

1.检查类是否被加载。 当虚拟机遇到new指令后,会先去常量池检查有没有该类的符号引用,并且检查这个类有没有进行加载、解析、初始化过,没有就先执行类加载过程。 2.为对象分配内存空间*。 ...

曦鱼violet
59分钟前
26
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部