什么是JVM
JVM全程为Java Virtual Machine,也就是Java程序的运行环境(Java二进制字节码的运行环境)。
我们平时写个Java程序就可以被计算机识别的原因都是因为Jvm帮我们把.java文件编译后的.class文件进行了处理。
使用JVM的好处有:
- 一次编写,到处运行
- 自动内存管理,垃圾回收功能
- 数组下标越界检查
- 多态
JVM、JRE、JDK的区别:
JVM:Java虚拟机,屏蔽Java代码与底层操作系统的联系
JRE:JVM+基础类库(如我们常用的Math库、Date and Time库等等)
JDK:JVM+基础类库+编译工具与文档(如javac、JConsole、javadoc等等)
其实这三者之间的关系就是包含与被包含的关系
内存结构
在讲解内存结构之前,我们先来看一张图,留下个印象就行
方法区
JVM用来存储加载的类信息、常量、静态变量、编译后的代码等数据。
方法区很少发生GC,这里的GC主要是对方法区的常量池和对类型的卸载
常量池就是存放在这里的
特点:
- 线程共享
- 有垃圾回收机制
JDK1.8使用MetaSpace(元空间)替代方法区,MetaSpace并不在JVM中,而是使用的本地内存。
堆
JVM用来存放对象的实例(垃圾回收器主要就是管理堆内存)。
特点:
- 线程共享
- 有垃圾回收机制
虚拟机栈
由多个栈帧组成,栈帧内容包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。
一个线程会执行一个或多个方法,一个方法对应一个栈帧。
栈帧内容:
- 局部变量表:就是存储局部变量;
- 操作数栈:栈的结构【先进后出】,用来存储操作数;
- 动态链接:动态链接将这些符号方法引用转换为具体的方法引用,根据需要加载类以解析尚未定义的符号,并将变量访问转换为与这些变量的运行时位置关联的存储结构中的适当偏移量。
- 方法返回地址:记录一个方法执行完成之后返回的地方;
特点:
- 线程私有
- 栈帧过多或者过大都会导致内存溢出
程序计数器
记录下一条Jvm指令的执行地址,存储的是字节码指令地址(不记录Native方法)。
特点:
- 线程私有
- 不会出现内存溢出
- 占用内存少
为什么需要程序计数器?
答:CPU同一时间,只会执行一条线程中的指令,JVM多线程会轮流切换并且分配CPU执行时间的方式,为了保证切换后能够正确恢复执行位置,需要引用一个类似于位置记录仪的功能(程序计数器)。
本地方法栈
和虚拟机栈功能类似,不过本地方法栈只存放Native方法。
特点:
- 线程私有
什么是Native方法?
答:方法名前面使用Natice修饰,不是由Java语言实现,而是以本地语言实现的(比如 C 或 C++)。如我们常在Thread类中调用的sleep方法等。
看完后在跟着这个图理解试试,是不是很轻松啦!!!