从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-08-08 09:34:50

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

Java内存模型和JVM内存管理

Java内存模型和JVM内存管理   一.Java内存模型: 1.主内存和工作内存(即是本地内存): Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取出变量这样的底层细节.此处的变量与Java编程里面的变量有所不同步,它包含了实例字段.静态字段和构成数组对象的元素,但不包含局部变量和方法参数,因为后者是线程私有的,不会共享,当然不存在数据竞争问题(如果局部变量是一个reference引用类型,它引用的对象在Java堆中可被各个线程共享,但是ref

Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收

很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确实很低,一方面,Java语言采用面向对象思想,这也决定了其必然是开发效率高,执行效率低.另一方面,Java语言对程序员做了一个美好的承诺:程序员无需去管理内存,因为JVM有垃圾回收(GC),会去自动进行垃圾回收. 其实不然: 1.垃圾回收并不会按照程序员的要求,随时进行GC. 2.垃圾回收并不会及时

java jvm内存管理/gc策略/参数设置

1. JVM内存管理:深入垃圾收集器与内存分配策略 http://www.iteye.com/topic/802638 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项技术当做Java语言的伴生产物.事实上GC的历史远远比Java来得久远,在1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期,

java基础---JVM内存管理以及内存运行机制学习总结

自己从网上搜资料拼接了一张JVM内存图:如下图所示: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的 方式去实 现),字节码解释器工作时就是通过改

java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任. 对于Java程序员来说,不需要在为每一个new操作去写配对的delete/free,不容易出现内容泄漏和内存溢出错误,看起来由JVM管理内存一切都很美好.不过,也正是因为Java程序员把内存控制的

详解JVM内存管理与垃圾回收机制 (上)

Java应用程序是运行在JVM上的,得益于JVM的内存管理和垃圾收集机制,开发人员的效率得到了显著提升,也不容易出现内存溢出和泄漏问题.但正是因为开发人员把内存的控制权交给了JVM,一旦出现内存方面的问题,如果不了解JVM的工作原理,将很难排查错误.本文将从理论角度介绍虚拟机的内存管理和垃圾回收机制,算是入门级的文章,希望对大家的日常开发有所助益. 一.内存管理 也许大家都有过这样的经历,在启动时通过-Xmx或者-XX:MaxPermSize这样的参数来显式的设置应用的堆(Heap)和永久代(P

你应该这样理解JVM内存管理

在进行Java程序设计时,一般不涉及内存的分配和内存回收的相关代码,此处引用一句话: Java和C++之间存在一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外的人想进去,墙里面的人想出来 ,个人从这两句话中,捕获到了 两个点 . java的自动内存管理机制,极大的节省了开发人员的精力,避免了易错且复杂的内存管理设计,相对于手动的内存管理这是极大的飞跃.java自动内存管理机制,其不能根据具体的场景提供最优的内存管理,其只提供普适的内存管理机制.想比于C++的手动内存管理,灵活性不够,存在制约系

JVM内存管理和垃圾回收机制介绍

http://backend.blog.163.com/blog/static/20229412620128233285220/ 内存管理和垃圾回收机制是JVM最核心的两个组成部分,对其内部实现的掌握是Java开发人员开发出高质量的Java系统的必备条件.最近整理了一些关于JVM内存管理和垃圾回收方面的知识,这里梳理一下,分享给大家,希望能够对Java虚拟机有更深入的了解. 1. JVM内存管理 首先,JVM将内存组织为主内存和工作内存两个部分.主内存中主要包括本地方法区和堆.每个线程都有一个工

JVM内存管理(二)

JVM内存管理 JVM在执行java程序的过程中,会把内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁. 程序计数器 程序计数器:当前线程所执行字节码的行号指示器. 由于JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令.为了线程切换后能够恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各线程之间计数器