JVM笔记----Java虚拟机内部结构介绍
Java与c++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外的人想进去,墙里面的人却想出来。
—— 《深入理解Java虚拟机》 周志明
对于c++来说 , 在内存管理领域,他们既是拥有最高权利的皇帝,又是从事最基础工作的劳动人民。他们拥有每一个对象的
所有权,又背负着维护每一个对象的责任。
而对于Java程序员来说,在JVM的帮助下,不再需要为每一个new 操作去写配对的delete / free 代码,不容易出现内存泄漏
和内存溢出的问题。
那么就然我们来一探JVM的底层结构吧~
上图就是JVM的结构啦~ 那么下面就让我来 一 一 介绍 每块区域的职责和特点
当我们把java程序写出来的时候,首先要对它进行编译才可以运行,比如上图的Math类,我们要首先用javac指令
把它编译生成字节码文件( .class ) , 然后就可以运行了,而运行时的内存管理就依赖于JVM,由JVM对我们的内存
进行管理。
程序计数器:
想必学过计算机组成原理的同学对程序计数器都不陌生吧~ 它负责记录我们的代码运行到哪一行,以及负责一些流程控制。
字节码解释器工作时会通过改变计数器的值来选去下一条指令,分支,循环,跳转,异常处理,线程恢复都需要计数器。
每条线程都需要一个独立计数器,各线程计数器互不影响,这类内存区域称为“线程私有”内存。
栈(线程):
线程私有,生命周期与线程相同。
每个方法在执行的时候会创建一个栈帧 用于存储 局部变量表 、 操作数栈 、 动态链接 、 方法出口
每一个方法从调用直到执行完成的过程,就对应一个栈帧在虚拟机中入栈到出栈的过程。
局部变量表: 存放各种基本数据类型 ( boolean , byte , char , short , int , float , long , double ) 没有 String!
对象引用 ( 指向对象起始地址的指针 )
return Address 类型 (指向一条字节码指令的地址)
它有哪些异常呢? 有:线程请求的栈深度大于JVM所允许,StackOverflowError
若栈可以动态扩展,无发申请到足够内存时,OutOfMemoryError
本地方法栈:
与虚拟机栈区别:虚拟机栈为JVM执行Java方法服务
方法栈为JVM使用到的Native方法服务
也会抛出StackOverflowError, OutOfMemoryError
堆:
内存最大 被所有线程共享
几乎所有的对象实例和数组都要在堆中分配内存(除了静态等)
若在堆中没有内存完成实例分配,且堆无法扩展时,抛出OutOfMemoryError
方法区:
各线程共享
用于存储类信息,常量,静态变量,编译后的代码
垃圾收集很少出现
运行时常量池:
方法区的一部分
存放编译期生成的各种字面量和符号引号(常量池)
这部分内容在类加载后进入方法区的运行时常量池中存放
直接内存:
不是JVM运行时数据区的一部分,也不是JVM规范中定义的内存区域
那么今天的JVM就介绍到这里~
下一次我会介绍JVM是如何创建对象的哦~