从JVM内存管理的角度谈谈JAVA类的静态方法和静态属性

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

一般,JVM的内存分为两部分:Stack和Heap。(stack和heap都是位于RAM中的)

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中丢失了对象地址的无用对象清除了),这就是垃圾收集的过程。

 

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

 

为了便于描述,我简单的统称:

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中的(基本类型保存在stack中,对象类型地址保存在stack,值保存在heap 中),而不同于动态属性保存在heap 中。正因为都是在stack中,而stack中指令和数据都是定长的,因此很容易算出偏移量,也因此不管什么指令(类的方法),都可以访问到类的静态属性。也正因为静态属性被保存在stack中,所以具有了全局属性。

 

总结一下:静态属性保存在stack指令内存区,动态属性保存在heap 数据内存区。

 

转载链接:

http://www.189works.com/article-58284-1.html

 

http://blog.csdn.net/zhongyili_sohu/article/details/8031410

 

时间: 2024-07-29 20:27:47

从JVM内存管理的角度谈谈JAVA类的静态方法和静态属性的相关文章

JVM内存管理及GC机制

一.概述 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.经过这么长时间的发展,Java GC机制已经日臻完善,几乎可以自动的为我们做绝大多数的事情. 虽然java不需要开发人员显示的分配和回收内存,这对开发人员确实降低了不少编程难度,但也可能带来一些副作用: 1. 有可能不知不觉浪费了很多内存 2. JVM花

现代JVM内存管理方法的发展历程,GC的实现及相关设计概述(转)

JVM区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分:Code Cache(代码缓存区).Perm Gen(永久代).Jvm Stack(java虚拟机栈).Local Method Statck(本地方法栈). HotSpot虚拟机GC算法采用分代收集算法: 1.一个人(对象)出来(new 出来)后会在Eden Space(伊甸园)无忧无虑的生活,直

jvm的在连接阶段对java类的验证和编译器对源代码的编译有什么区别

问题描述 jvm的在连接阶段对java类的验证和编译器对源代码的编译有什么区别 问题补充:beneo 写道 解决方案 引用具体的话,你可以看看jvm spec,你不愿看的话,就看看http://rednaxelafx.iteye.com/ 的博客,如果还看不懂的话,就去问http://rednaxelafx.iteye.com/大大P.S. 其实该走的路我都告诉你了,你为何不往前踏一步呢?解决方案二:引用编译器对源代码的编译有什么区别 java source code -> java class

java 中的静态方法和静态代码块分别装载到哪个区

问题描述 java中的静态方法和静态代码块分别装载到哪个区 解决方案 解决方案二: 解决方案三:楼主可看看楼上说的挺好学习了顶解决方案四:应该是栈里解决方案五:方法都是在方法区中,无论是不是静态的.方法表中有一个代码属性,代码属性存放方法代码.解决方案六:好,收了解决方案七:谢谢1楼的,学习了!

JVM内存管理:JAVA语言的内存管理概述

引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓狂的内存溢出和泄露的问题. 可怕的事情还不只如此,有些使用其它语言开发的程序员,给JAVA程序员扣上了一个"不懂内存"的帽子,这着实有点让人难以接受.毕竟JAVA当中没有malloc和delete.没有析构函数.没有指针,刚开始接触JAVA的程序员们又怎么可能接触内存这一部分呢,更何况有不

JVM内存管理:GC算法精解---分代搜集算法

引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们的能力. 那么分代搜集算法是怎么处理GC的呢? 对象分类 上一章已经说过,分代搜集算法是针对对象的不同特性,而使用适合的算法,这里面并没有实际上的新算法产生.与其说分代搜集算法是第四个算法,不如说它是对前三个算法的实际应用. 首先我们来探讨一下对象的不同特性,接下来LZ和各位来一起给这些对象选择GC算法. 内存中的对象按照生命周期的长短大致可以分为三种

JVM内存管理:杂谈(借此也论一论obj=null)

各位园友好,LZ是从某网站转战过来的博主,看到这里很多博主都称看友们为园友,LZ斗胆模仿一下,不过以前,LZ其实都是称看友们为猿友的.之前LZ在某网站已经写了一系列文章,已经全部复制到了园内的新博客,主要是设计模式的内容,各位有兴趣的也可以去翻看一下,其中有不少还是颇受之前猿友们喜爱的. 作为一个程序猿,修炼的过程就犹如玄幻小说中的主角,不仅需要练习各种武技,内气的修炼的一样重要.虽然武技可以迅速的提升主角的实力,但是在内气太差的情况下,根本发挥不出武技的十之一二. 因此,在介绍过设计模式这一类

JVM内存管理 (转)

一.物理内存与虚拟内存1.物理内存                (1)RAM        所谓物理内存就是我们通常所说的RAM(随机存储器).        (2)寄存器        在计算机中,还有一个存储单元叫寄存器,它用于存储计算单元执行指令(如浮点.整数等运算时)的中间结果.寄存器的大小决定了一次计算可使用的最大数值.        (3)地址总线        连接处理器和RAM或者处理器和寄存器的是地址总线,这个地址总线的宽度影响了物理地址的索引范围,因为总线的宽度决定了处理器

JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代

如果大家想深入的了解JVM,可以读读周志明<深入理解Java虚拟机:JVM高级特性与最佳实践>      需要掌握的东西,包括以下内容.判断对象存活还是死亡的算法(引用计数算法.可达性分析算法).常见的垃圾收集算法(复制算法.分代收集算法等以及这些算法适用于什么代)以及常见的垃圾收集器的特点(这些收集器适用于什么年代的内存收集).            JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示.      JVM内存结构由程序计数器.堆.栈.本地