`
bruce.ko
  • 浏览: 33934 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Java Stack Heap Static Method

阅读更多

数据都存放在哪里?
1.寄存器。记得以前汇编里面有学习过,叫做register的东西,Java里面接触不到这个。
2.栈。Stack。放在RAM里面,随机存储器用来存储基础类型,例如short int long float double char byte boolean等,或者用来存储对象的引用。
例如:
A a = new A();
A b = a;
A c = a;
这里的b,c都是放在栈里面。
3.堆。Heap,也放在RAM里面,例子里面的a就是放在这里的。凡是new 出来的。。。不过String放在哪里的呢?是不是也放在这里呢?
String s = "abc";//这里"abc"存放在常量存储区,s是引用,所以s在栈里面。
String s2= new String("abc"); //s2是new出来的,所以在堆里面。
String s3 = "abc"+"def"; // 如果"abcdef"已经在常量存储器里面创建了,那么s3就是引用,放入Stack,否则s3就在堆里
4.静态存储区,也在RAM里面。也就是Static声明的字段都放在这里,那Static声明的方法和类是不是也放在这里呢?
5.常量存储区,在ROM,只读存储器。用来放final声明的。
6.非RAM中。例如数据库,例如网络流中,用那种持久化技术存起来就好了。

其实我们可以将上面的6个部分笼统的分为4个,寄存器,栈(包括栈,静态存储区,常量存储区),堆,非RAM。寄存器和非RAM不在我们讨论范围内。只关心栈和堆。
先来段程序。
主程序:
Test t = new Test();
t.see();

具体的类:
class Test{
static int s1=1;
String s2="abc";

public void see(){
int i=0;
System.out.println("see");
}
}
解释一下这段程序,先将主程序指令存入Stack,执行,第一句的时候,在Heap里面为t分配空间,建立对象实例的属性值,属性类型,以及对象本身的类型标记,在Stack里面建立对象的方法。最终将Heap里面t的4字节地址返给Stack中,等到t.see()调用的时候,see()方法默认传个隐藏参数进来,即调用see方法的对象的Heap地址,然后执行。
为什么静态方法不能调用非静态属性?
因为静态方法是最开始load进来的,放在Stack里,可以直接通过栈寻址找到它的,而非静态属性则是存放在Heap里面,只有实例化出具体对象才能存在。


下面转载一篇文章。。
从JVM内存管理的角度谈谈静态方法和静态属性

作者     robbin   (http://hibernate.fankai.com/站长)  
   
  我试着从JVM的内存管理原理的角度来谈一下静态方法和静态属性的问题,不对的地方请指正。  
  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中丢失了对象地址的无用对象清除了),这就是垃圾 收集的过程。  
   
  我们首先要搞清楚的是什么是数据,什么是指令?然后要搞清楚对象的方法和对象的属性分别保存在哪里?  
   
  为了便于描述,我简单的统称:  
   
  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数据内存区。
分享到:
评论
1 楼 potato_hi 2012-02-13  
A a = new A();
a 也是一个引用吧? 只是它指向的对象是在heap里。 a应该是在stack里的。

相关推荐

    java中带static关键字的程序内存分析

    - **堆(Heap)**:这是Java程序的主要内存区域,用于存储对象实例和其非静态成员。每个对象都有自己的堆内存空间,包含所有非静态字段。 - **栈(Stack)**:每个线程都有自己的程序计数器、Java虚拟机栈和本地...

    java内存机制

    - **组成**: 包括堆(Heap)、方法区域(Method Area)、Java栈(Java Stack)、程序计数器(Program Counter)以及本地方法栈(Native Method Stack)。 - **特点**: Heap和Method Area由所有线程共享;Java Stack...

    java虚拟机的详细原理

    3. **运行时数据区**(Runtime Data Area):包括方法区(Method Area)、堆(Heap)、程序计数器(Program Counter Register)、本地方法栈(Native Method Stack)和Java栈(Java Stack)等。 - **方法区**...

    JStack和Java Thread Dumps分析

    18 at java.lang.Object.wait(Native Method) 19 - waiting on <0x00000000c2002180> (a MyThread) 20 at MyThread.run(MyThread.java:10) 21 - locked <0x00000000c2002180> (a MyThread) 22 at java.lang.Thread....

    java虚拟机JVM详解ppt

    ##### 4.3 Java虚拟机栈(Java Virtual Machine Stack) Java虚拟机栈是线程私有的,用于存储方法执行的局部变量表、操作数栈、动态链接等信息。当线程请求的栈深度超过JVM允许的深度时,会抛出`StackOverflowError`...

    9 一段java代码是如何执行的?.docx

    - **本地方法栈(Native Method Stack)**:为Java方法以外的本地(非Java)方法服务。 - **Java堆(Heap)**:所有对象实例和数组的存储区域,是线程共享的。 - **Java栈(Java Stack)**:每个线程都有自己的...

    15 - ASM之方法Frame - 简书1

    其中,Runtime Data Areas包括Method Area、Heap Area、Stack Area、PC Registers和Native Method Stack等部分。 JVM Stack 在JVM Architecture中,每个线程(Thread)都对应一个属于自己的JVM Stack。当一个新...

    Top 1000 Java Interview Questions

    - **本地方法栈(Native Method Stack):** 用于支持本地方法调用。 - **方法区(Method Area):** 存储每个类的信息、常量、静态变量等数据。 4. **即时编译器(JIT Compiler)的作用:** - JIT编译器在运行时...

    Java最新面试题大全

    9. Java内存模型:包括堆(Heap)、栈(Stack)、方法区(Method Area)等内存区域的作用,以及垃圾回收机制。 10. Java I/O:包括流的概念,以及字节流(InputStream和OutputStream)和字符流(Reader和Writer)的...

    深入理解Java虚拟机笔记(带目录).docx

    深入理解 Java 虚拟机笔记 Java 虚拟机(JVM)是 Java 语言的运行环境,它负责解释和执行 Java 字节码。下面是 Java 虚拟机相关的知识点: 虚拟机内存结构 Java 虚拟机的内存结构主要包括以下几个部分: * 方法...

    java的一本好教材

    33. **堆(Heap)**:Java堆是程序中动态分配内存的区域,用于存储对象实例。 34. **标识符(Identifiers)**:标识符是用于命名类、变量、方法等的名称,遵循特定的命名规则。 35. **引入语法(Import statement...

    Java面试测试题目2018张大成总结

    - **interface**:所有的方法默认都是public abstract的,不能包含具体的实现方法(Java 8引入了默认方法),不允许有状态(成员变量只能是public static final)。 #### 5. final, finally, finalize的区别 - **...

    java名词速查表 java名词速查表

    #### Heap (堆) - 堆是Java虚拟机中用于存储对象的内存区域。 - **特点**:动态分配,垃圾回收的主要目标。 #### Identifiers (标识符) - 标识符用于命名变量、方法、类等。 - **规则**:以字母、下划线或美元...

    Java编程思想读书笔记

    - 栈(Stack):存放基本类型的变量和对象引用,但对象本身存储在堆(Heap)中。 - 堆(Heap):存储通过new关键字创建的对象。 - 静态存储(Static Storage):存储类中的静态成员变量。 - 常量存储(Constant ...

    Java数据存储

    ### Java数据存储详解 在Java编程中,理解数据如何存储对于优化程序性能至关重要。本文将深入探讨Java数据存储的关键概念,包括堆栈、堆、数据区等,以及它们各自的特点和适用场景。 #### 一、堆栈(Stack) 堆栈...

    C++JAVA内存分配.pdf

    4. **本地方法栈(Native Method Stack)**:与C++的栈类似,但主要用于支持JNI(Java Native Interface)调用的本地方法。 5. **运行时常量池(Runtime Constant Pool)**:这是方法区的一部分,包含了类和接口的...

    Java核心_Java内存分配原理精讲(完整版).pdf

    1. **栈(Stack)**: 栈主要用于存储基本类型的数据(如int、double)和对象的引用。当在函数或代码块中声明一个变量时,Java会在栈中为它分配内存。一旦变量超出其作用域,栈会自动释放该变量的内存。对于对象,...

    附录:Java的内存分配

    每当程序进入一个新的方法调用时,Java虚拟机(JVM)会在栈区分配一块内存作为栈帧(Stack Frame),用于存储方法中的局部变量。这些局部变量包括基本数据类型和引用类型。对于基本类型,其值直接存储在栈中;而对于...

    java面试150题

    10. **JVM内存模型**:Java虚拟机内存分为堆内存(Heap)、栈内存(Stack)、方法区(Method Area)、本地方法栈(Native Method Stack)和程序计数器(PC Register)五大部分,分别负责存储不同类型的变量和执行...

    java面试题目.docx

    - 静态类:在Java中,静态类是嵌套类的一种,它被声明为static,不能有实例,只能通过其包含类的实例来访问。静态类主要用于组织代码,它们不能继承其他类,也不能被其他类继承。 - 抽象类:抽象类是不能实例化的...

Global site tag (gtag.js) - Google Analytics