Java虚拟机结构

来源:互联网 发布:创建表时外键的sql语句 编辑:程序博客网 时间:2024/05/29 07:21

虚拟机基本结构

类加载子系统:负责从文件或者网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间。除了类的信息外,方法区中可能还会存放运行时常量池信息,包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)。

Java堆:在虚拟机启动时建立,是Java程序中最主要的内存工作区域。几乎所有的Java对象实例都存放于Java堆中。堆空间是所有线程共享的,是一块与Java应用密切相关的内存区间。

直接内存:Java的NIO库允许Java程序使用直接内存;是在Java堆外的、直接向系统申请的内存区间。通常,访问直接内存速度会优于Java堆。因此出于性能考虑,读写频繁的场合会考虑使用直接内存。其不受限与最大堆大小而受限于操作系统能给的最大内存。

垃圾回收系统:可以对方法区、Java堆和直接内存进行回收;堆是垃圾收集器的工作重点。

Java栈:每一个Java虚拟机线程都有一个私有的Java栈;一个线程的Java栈在线程创建的时候被创建;Java栈中保存着帧信息、局部变量、方法参数,同时和Java方法的调用、返回密切相关。

本地方法栈:与Java栈非常类似,其最大不同在于Java栈用于Java方法调用,而本地方法栈则用于本地方法调用(C编写)。

PC寄存器:是每个线程私有的空间,Java虚拟机会为每一个Java线程创建PC寄存器。在任意时刻,一个Java线程总是在执行一个方法,这个正在被执行的方法称为当前方法。如果当前方法是本地方法,那么PC寄存器的值就是undefined。

执行引擎:负责执行虚拟机的字节码;为了提高执行效率,会使用即时编译技术将方法编译成机器码后再执行。

Java栈

可以在启动JVM虚拟机时通过-Xss来指定线程的最大栈空间。
测试代码:

public class TestStackDeep {    private static int count = 0;    public static void recursion() {        count++;        recursion();    }    public static void main(String[] args) {        try {            recursion();        } catch (Throwable e) {            System.out.println("deep of calling=" + count);            e.printStackTrace();        }    }}

在-Xss参数为128K时:

deep of calling=2493

在-Xss参数为256K时:

deep of calling=5798

局部变量表

用于保存函数的参数以及局部变量。局部变量表中的变量只在当前函数调用中有效,当函数结束后,随着函数栈帧的销毁,局部变量表也会随之销毁。

public class TestStackDeep {    private static int count = 0;    public static void recursion(long a, long b, long c) {        long e = 1, f = 2, g = 3, h = 4, i = 5, j = 6, k = 7, l = 8, m = 9, n = 10;        count++;        recursion(a, b, c);    }    public static void main(String[] args) {        try {            //该函数中含有3个参数和10个局部变量,因此其局部变量表中含有13个变量            recursion(1l, 2l, 3l);        } catch (Throwable e) {            System.out.println("deep of calling=" + count);            e.printStackTrace();        }    }}

在-Xss参数为128K时:

deep of calling=700

在-Xss参数为256K时:

deep of calling=1600

之所以调用次数明显减少是因为参数以及局部变量占用空间导致的。

局部变量表中的槽位是可以复用的。

    public void localvar2() {        {            int a = 0;            System.out.println(a);        }        int b = 0;    }

前提是该变量超出其作用域。

操作数栈

用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。
操作数栈是一个先进后出的数据结构,只支持入栈和出栈两种操作。

栈数据区

用于常量池解析、正常方法返回和异常处理;大部分Java字节码指令需要进行常量池访问,在帧数据区保存着访问常量池的指针,方便程序访问常量池。

参考资料:
实战Java虚拟机:JVM故障诊断与性能优化

源码

0 0