jvm运行时数据区

Runtime data area 主要包括五个部分:Heap (堆), Method Area(方法区域),Java Stack(java 的栈), Program Counter(程序计数器), Native method stack(本地方法栈)。Heap 和Method Area 是被所有线程的共享使用的;而Java stack, Program counter 和Native method stack 是以线程为粒度的,每个线程独自拥有。

Heap
Java 程序在运行时创建的所有类实或数组都放在同一个堆中。而一个Java 虚拟实例中只存在一个堆空间,因此所有线程都将共享这个堆。每一个java 程序独占一个JVM 实例,因而每个java 程序都有它自己的堆空间,它们不会彼此干扰。但是同一java 程序的多个线程都共享着同一个堆空间,就得考虑多线程访问对象(堆数据)的同步问题。(这里可能出现的异常java.lang.OutOfMemoryError:
Java heap space)

Method area
在Java 虚拟机中,被装载的class 的信息存储在Method area 的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class 文件,然后读入这个class 文件内容并把它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。与Heap 一样,method area 是多线程共享的,因此要考虑多线程访问的同步问题。比如,假设同时两个线程都企图访问一个名为Lava 的类,而这个类还没有内装载入虚拟机,那么,这时应该只有一个线程去装载它,而另一个线程则只能等待。(这里可能出现的异常java.lang.OutOfMemoryError: PermGen full)

Java stack
Java stack 以帧为单位保存线程的运行状态。虚拟机只会直接对Java stack 执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时候,就对当前状态作为一个帧保存到java stack 中(压栈);当一个方法调用返回时,从java stack 弹出一个帧(出栈)。栈的大小是有一定的限制,这个可能出现StackOverFlow 问题。下面的程序可以说明这个问题。
public class TestStackOverFlow {
public static void main(String[] args) {
Recursive r = new Recursive();
r.doit(10000);
// Exception in thread "main"
java.lang.StackOverflowError
}
}
class Recursive {
public int doit(int t) {
if (t <= 1) {
return 1;
}
return t + doit(t - 1);
}
}

Program counter
每个运行中的Java 程序,每一个线程都有它自己的PC 寄存器,也是该线程启动时创建的。PC 寄存器的内容总是指向下一条将被执行指令的内存地址,这里的内存地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。

Native method stack
对于一个运行中的Java 程序而言,它还能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,不止与此,它还可以做任何它想做的事情。比如,可以调用寄存器,或在操作系统中分配内存等。总之,本地方法具有和JVM 相同的能力和权限。(这里出现JVM 无法控制的内存溢出问题native heap OutOfMemory )

你可能感兴趣的:(jvm)