Wednesday, March 18, 2009

Java程序运行时,各变量在JVM中存放的位置

Java程序运行时,各变量在JVM中存放的位置

JVM对于内存是通过分成不同的部分来管理的,主要包括方法区(Method Area),堆(Heap),Java栈(Stack)。其中方法区存放装载到JVM中的类的信息,堆存放类的实例对象,Java棧以帧为单位保存线程运行的状态,存放每一个线程在程序执行过程中需要的数据信息。
对应于Java文件中的各种类变量,实例变量,类本身等内容,下面阐述一下它们在JVM中的存放位置。
public static final int i =1;
这个i在编译时就可以确认它的值,因此它作为一个常量被直接写在.class文件中,其它类用到这个i的时候,在编译过程中会拷贝i的值到该类的.class文件中。
public static final int i = (int)(Math.random() * 4);
如果是以上面这种形式的定义变量,因为其在编译时无法确认其值,在运行过程中才会确定值,因此它会当作一个类变量在类初始化是存放在方法区中。

static int i = 9;
以上这种形式定义的变量在类初始化时被初始化正确的值,并将其与类信息一起存放在方法区。

int i = 9;
这种形式定义的变量是实例变量,在类被实例化时赋于正确的初始值,和类实例对象一起存放在堆区。

void getXX(int a){
int i = 1;
}
上面这种形式定义的变量a是一个参数,i是一个局部变量,只在运算过程在有效,因此会存放在Java棧中棧帧中,在方法返回后其值也会无效,等待GC回收。


通过上面的论述可以推断出有哪些情况可能会导致OutOfMemory的错误了。
1、过多的类信息被装载到方法区,导致该区域OutOfMemory错误,在一些框架中通过反射机制生成大量的类信息可能导致该问题。
2、使用过多的static类型的类变量,特别是将大的数组,字符串等,导致方法区占用内存过多,造成OutOfMemory错误。由于JVM中并没有提供设置方法区大小的参数,因此只能通过加大JVM的内存来解决。
3、程序创建了过多的线程,导致Java棧使用内存过多,导致OutOfMemory。可通过-Xss来设置每一个Java thread stack 的大小来解决该问题。
4、程序生成了过多的实例对象,使得堆占用大量内存,最终出现OutOfMemory错误。 该问题可通过设置下面两个JVM启动参数来避免:
-Xms set initial Java heap size
-Xmx set maximum Java heap size

No comments:

Post a Comment