学习JVM有什么用?
-
面试
-
理解底层的实现原理
-
中高级程序员的必备技能
常见的JVM
学习路线
2.1 程序计数器
2.1.1 定义
Program Counter Register 程序计数器(寄存器)
2.1.2 作用
作用:记住下一条jvm指令的执行地址
特点:
-
是线程私有的
-
不会存在内存溢出
2.2 虚拟机栈
2.2.1 定义
Java Virtual Machine Stacks(Java 虚拟机栈)
-
每个线程运行时需要内存,称为虚拟机栈
-
每个栈由多个栈帧(Frame)组成、对应着每次方法调用时所占用的内存
-
每个线程只能有一个活动栈帧,对应着正在执行的那个方法
演示
package com.caopeng.jvm.t1;
/**
-
@author Crescent_P
-
@date 2022-01-05 19:34
*/
public class Demo1_1 {
public static void main(String[] args) {
method1();
}
private static void method1() {
method2(1,2);
}
private static int method2(int a, int b) {
int c = a + b;
return c;
}
}
问题辨析
- 垃圾回收是否涉及栈内存?
答:不涉及,因为栈内存是一次次方法调用产生的栈帧内存、每次方法调用完之后,栈帧会被弹栈,会自动地被回收掉。
- 栈内存的分配越大越好吗?
答:不是,因为物理内存是一定的,栈内存越大、线程数会变少。
- 方法内的局部变量是否线程安全?
答:判断是否线程安全、就是看多个线程对这个变量是否共享。一个线程对应一个虚拟机栈、一个方法对应一个栈帧,那么方法内的局部变量是对于这个线程来说是私有的。
package com.caopeng.jvm.t1;
/**
-
@author Crescent_P
-
@date 2022-01-05 21:21
-
局部变量的线程安全问题
如果方法内局部变量没有逃离方法的作用范围,那就是线程安全的
如果局部变量引用了对象,并逃离了方法的作用范围,需要考虑线程安全问题
*/
public class Demo1_3 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append(4);
sb.append(5);
sb.append(6);
// 创建一个新的进程
new Thread(()->{
m2(sb);
}).start();
}
// 不存在线程安全问题
public static void m1(){
// 方法内的局部变量
StringBuilder sb = new StringBuilder();
sb.append(1);
sb.append(2);
sb.append(3);
System.out.println(sb.toString());
}
// 存在线程安全问题
// 作为参数,有可能有其它的线程访问到它
public static void m2(StringBuilder sb){
sb.append(1);
sb.append(2);
sb.append(3);
System.out.println(sb.toString());
}
// 不能
// 会将sb返回,那么其它进程就可能拿到这个sb
public static StringBuilder m3(){
StringBuilder sb = new StringBuilder();
sb.append(1);
sb.append(2);
sb.append(3);
return sb;
}
}
2.2.2 栈内存溢出
栈帧过多导致栈内存溢出
栈帧过大导致栈内存溢出
演示
package com.caopeng.jvm.t1;
/**
-
@author Crescent_P
-
@date 2022-01-05 21:31
-
显示栈内存溢出
-
-Xss256K
*/
public class Demo1_4 {
private static int count;
public static void main(String[] args) {
try{
method1();
}catch(Throwable e){
e.printStackTrace();
System.out.println("count " + count); // count 34205
}
}
// 没有终止条件,会一直递归调用
private static void method1(){
count++;
method1();
}
}
package com.caopeng.jvm.t1.stack;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.List;
/**
-
@author Crescent_P
-
@date 2022-01-05 21:36
-
json 数据转化
*/
public class Demo1_5 {
public static void main(String[] args) throws JsonProcessingException {
Dept d = new Dept();
d.setName(“Market”);
Emp e1 = new Emp();
e1.setName(“zhang”);
e1.setDept(d);
Emp e2 = new Emp();