目录
一、JVM基本介绍——概念、组成、重点
二、JVM组成
javap -v xx.class #打印堆栈大小,局部变量的数量和方法的参数
JVM(Java Virtual Machine,即java虚拟机),java程序的运行环境(java二进制字节码的运行环境)。
JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。针对java用户,也就是拥有可运行的.class文件包(jar或者war)的用户。里面主要包含了jvm和java运行时基本类库(rt.jar)。rt.jar可以简单粗暴地理解为:它就是java源码编译成的jar包。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java能够“一次编译,到处运行”的原因。
JVM是Java跨平台的关键,因为它屏蔽了不同操作系统之间的差异,可以让相同的Java程序在不同的操作系统上运行出相同的结果。
好处:
我们在 JVM常见面试题(一):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别 中已详细介绍过JDK、JRE、JVM的联系与区别,此处简单讲解下:
JDK(Java Development Kit,Java开发工具包)、JRE(Java Runtime Environment,Java运行时环境)、JVM(Java Virtual Machine,即java虚拟机)。
JDK是 Java 语言的软件开发工具包(SDK)。在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib合起来就称为jre。
程序计数器:线程私有的,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。
javap -v xx.class #打印堆栈大小,局部变量的数量和方法的参数
线程共享的区域:主要用来保存对象实例,数组等,当堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
Java堆主要组成部分:
总结:你能详细地介绍Java堆吗?
Java Virtual machine Stacks (java 虚拟机栈),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个栈帧(stack Frame) ,对应着一次次的Java方法调用。一次方法的调用,就是栈帧入栈到出栈的过程;
虚拟机栈是线程私有的,生命周期和线程一致,其作用为 主管Java程序的运行,它保存方法的局部变量(8大基本数据类型、对象的引用地址)、部分结果,并参与方法的调用和返回
每个线程都有自己的栈,栈中的数据都是以栈帧(stack Frame)的格式存在。栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息,存储:局部变量表(Local variables)、操作数栈(operand stack) (或表达式栈)、动态链接(Dynamic Linking) (或指向运行时常量池的方法引用)、方法返回地址(Return Address) (或方法正常退出或者异常退出的定义)、一些附加信息
多线程下
public class StackTest {
public static void main(String[] args) {
StackTest stackTest = new StackTest();
stackTest.methodA();
}
public void methodA() {
int i = 10;
int j = 20;
methodB();
}
private void methodB() {
int k = 30;
int m = 40;
}
}
补充:本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的。其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
垃圾回收主要指就是堆内存,不涉及栈内存,当栈帧弹栈以后,内存就会释放。
1)什么是垃圾回收?
垃圾回收(Garbage Collection,GC),顾名思义就是释放垃圾占用的空间,防止内存泄露。有效地使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。
2)结合2.5,因为栈帧对应的方法执行完后,栈会将该方法对应的栈帧弹出栈,释放内存,因此垃圾回收不涉及栈内存。
未必,默认的栈内存通常为1024k
栈帧过大会导致线程数变少,例如,机器总内存为512m,目前能活动的线程数则为512个(512m/1024k=512);如果把栈内存改为2048k,那么能活动的栈帧就会减半(512m/2048k=256)
(栈内存的大小不会影响方法执行的速度,而且由于计算机硬件的储存大小是有限的,栈空间内存设置过大,创建线程数量较多时会出现栈内存溢出OutofMemoryError,导致最大线程数减少,得不偿失。同时,栈内存也决定方法调用的深度,栈内存过小则会导致方法调用的深度较小,如递归调用的次数较少)
public static void m4(){
m4();
}
java.lang.StackOverflowError
常量池
可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
javap -v Application.class #查看字节码结构(类的基本信息、常量池、方法定义)
运行时常量池
常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
直接内存:并不属于JVM中的内存结构,不由JVM进行管理。是虚拟机的系统内存,常见于 NIO 操作时,用于数据缓冲区,它分配回收成本较高,但读写性能高。
举例:Java代码完成文件拷贝
常规IO的数据拷贝流程
1)什么是程序计数器
线程私有的,每个线程一份,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。
2)你能详细地介绍Java堆吗
3)什么是虚拟机栈
每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个栈帧(stack Frame) ,对应着一次次的Java方法调用。一次方法的调用,就是栈帧入栈到出栈的过程。
4)垃圾回收是否涉及栈内存
垃圾回收主要指就是堆内存,不涉及栈内存,当栈帧弹栈以后,内存就会释放。
5)栈内存分配越大越好吗
未必,默认的栈内存通常为1024k,栈帧过大会导致线程数变少。
6)方法内的局部变量是否线程安全
7)什么情况下会导致栈内存溢出
8)堆栈的区别是什么
9)解释一下方法区
10)介绍一下运行时常量池
11)直接内存
参考 黑马程序员相关视频与笔记
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。