《深入理解Java虚拟机》:Java内存区域

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域 , 这些区域称作运行时数据区域 , 分为5个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区 。
这是在网上找的一张图 , 今天就来把各个区的用途和创建销毁时机来说一下 。
《深入理解Java虚拟机》:Java内存区域文章插图
1、程序计数器:它是当前程序执行的字节码的行号指示器 , jvm执行引擎具体要执行哪一行指令 , 是由程序计数器来指示的 。 javap是jkd自带的反编译命令 , 在命令行执行以下命令 , 得到MyStack的字节码文件 , 程序计数器指示的就是#1,#2,#3之类的行号:
javap -verbose MyStack.class > MyStack.txtConstant pool:#1 = Class#2//com/bill99/MyStack#2 = Utf8com/bill99/MyStack#3 = Class#4//java/lang/Object#4 = Utf8java/lang/Object#5 = Utf8#6 = Utf8()V#7 = Utf8Code#8 = Methodref#3.#9//java/lang/Object."":()V#9 = NameAndType#5:#6//"":()V#10 = Utf8LineNumberTable#11 = Utf8LocalVariableTable#12 = Utf8this#13 = Utf8Lcom/bill99/MyStack;#14 = Utf8print#15 = Fieldref#16.#18//java/lang/System.out:Ljava/io/PrintStream;#16 = Class#17//java/lang/System#17 = Utf8java/lang/System#18 = NameAndType#19:#20//out:Ljava/io/PrintStream;#19 = Utf8out#20 = Utf8Ljava/io/PrintStream;#21 = String#22//print()#22 = Utf8print()#23 = Methodref#24.#26//java/io/PrintStream.println:(Ljava/lang/String;)V#24 = Class#25//java/io/PrintStream#25 = Utf8java/io/PrintStream#26 = NameAndType#27:#28//println:(Ljava/lang/String;)V#27 = Utf8println#28 = Utf8(Ljava/lang/String;)V#29 = Utf8main#30 = Utf8([Ljava/lang/String;)V#31 = Methodref#1.#9//com/bill99/MyStack."":()V#32 = Methodref#1.#33//com/bill99/MyStack.print:()V#33 = NameAndType#14:#6//print:()V#34 = Utf8args#35 = Utf8[Ljava/lang/String;#36 = Utf8myStack#37 = Utf8SourceFile#38 = Utf8MyStack.java2、虚拟机栈:每个方法在执行的时候都会创建一个栈帧 , 用于存储局部变量、操作数栈、动态链接、方法出口等信息然后压入虚拟机栈 , 每一个方法结束对应出栈的操作 。 如下示例代码 , debug调用栈也是main()方法先入栈 , 然后print()入栈 , print()执行结束出栈 , main()执行 。
如下public class MyStack{ public void print(){System.out.println("print()"); } public static void main(String[] args) {MyStack myStack = new MyStack();myStack.print(); }}
《深入理解Java虚拟机》:Java内存区域文章插图
这块区域常见异常有两种:线程请求栈的深度大于虚拟机栈所允许的深度 , 将抛出StackOverflowError;栈扩展的时候无法申请到足够内存空间 , 则抛出OutOfMemoryError 。
改写一下print()方法 , 让它不断递归调用自己 , 可以看到栈深度到1万以上抛异常了 。
private static int depth = 0;public void print(){System.out.println("print()"+(++depth));print();}print()11422Exception in thread "main" java.lang.StackOverflowError3、本地方法栈:由于java代码本身的限制 , 有些和操作系统直接交互的方法 , 可能是基于c或者c++编写的 , java代码可以通过本地方法间接的去调用操作系统底层的一些功能 。 本地方法运行时使用的内存空间就是本地方法栈 。 比如Thread类的一些方法 , 如下:
public static native Thread currentThread();public static native void yield();


推荐阅读