Python 官方文档:入门教程 => 点击学习
目录一、JVM 入门介绍JVM 定义JVM 优势JVM JRE jdk的比较学习步骤二、内存结构整体架构1、程序计数器(寄存器)1.1 作用1.2 特点2、虚拟机栈2.1 定义2.2
Java Virtual Machine,JAVA程序的运行环境(JAVA二进制字节码的运行环境)
注:我们笔记所使用的的是HotSpot 版本
JVM JRE JDK的区别:
学习顺序如下图:(由简到难)
Program Counter ReGISter
程序计数器用于保存JVM中下一条所要执行的指令的地址
0:getstatic #20 // PrintStream out = System.out;
1:astore_1 // --
2:aload_1 // out.println(1);
3:iconst_1 // --
4:invokevirtual #26 // --
5:aload_1 // out.println(2);
6:iconst_2 // --
7:invokevirtual #26 // --
8:aload_1 // out.println(3);
9:iconst_3 // --
10:invokevirtual #26 // --
11:aload_1 // out.println(4);
12:iconst_4 // --
13:invokevirtual #26 // --
14:aload_1 // out.println(5);
15:iconst_5 // --
16:invokevirtual #26 // --
return
Java指令执行流程:
Java Virtual Machine Stacks
代码
public class Demo01 {
public static void main(String[] args) {
methodA();
}
private static void methodA() {
methodB(1, 2);
}
private static int methodB(int a, int b) {
int c = a + b;
return c;
}
}
我们打断点来Debug 一下看一下方法执行的流程:
接这往下走,使方法B执行完毕:
然后方法A执行完毕,其对应的栈帧出栈,main方法对应的栈帧为活动栈帧;最后main执行完毕 栈帧出栈,虚拟机栈为空,代码运行结束!
3.方法内的局部变量是否是线程安全的?
从图中得出:局部变量如果是静态的可以被多个线程共享,那么就存在线程安全问题。如果是非静态的只存在于某个方法作用范围内,被线程私有,那么就是线程安全的!
看一个案例:
public class Demo02 {
public static void main(String[] args) {// main 函数主线程
StringBuilder sb = new StringBuilder();
sb.append(4);
sb.append(5);
sb.append(6);
new Thread(() -> {// Thread新创建的线程
m2(sb);
}).start();
}
public static void m1() {
// sb 作为方法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 作为方法m2()外部的传递来的参数,sb 不在方法m2()的作用范围内
// 不是线程私有的 ---> 非线程安全
sb.append(1);
sb.append(2);
sb.append(3);
System.out.println(sb.toString());
}
public static StringBuilder m3() {
// sb 作为方法m3()内部的局部变量,是线程私有的
StringBuilder sb = new StringBuilder();// sb 为引用类型的变量
sb.append(1);
sb.append(2);
sb.append(3);
return sb;// 然而方法m3()将sb返回,sb逃离了方法m3()的作用范围,且sb是引用类型的变量
// 其他线程也可以拿到该变量的 ---> 非线程安全
// 如果sb是非引用类型,即基本类型(int/char/float...)变量的话,逃离m3()作用范围后,则不会存在线程安全
}
}
该面试题答案:
如果方法内局部变量没有逃离方法的作用范围,则是线程安全的
如果局部变量引用了对象,并逃离了方法的作用范围,则需要考虑线程安全问题
Java.lang.stackOverflowError 栈内存溢出
发生原因
举2个案例:
案例1:
public class Demo03 {
private static int count;
public static void main(String[] args) {
try {
method1();
} catch (Throwable e) {
e.printStackTrace();
System.out.println(count);
}
}
private static void method1() {
count++;// 统计栈帧个数
method1();// 方法无限递归,不断产生栈帧 到虚拟机栈
}
}
最后输出结果:
java.lang.StackOverflowError
at com.haust.jvm_study.demo.Demo03.method1(Demo03.java:21)
...
...
39317// 栈帧个数,不同的虚拟机大小能存放的栈帧数量不一样
我们可以通过修改参数来指定虚拟机栈内存大小
当我们将虚拟机栈内存缩小到指定的256k的时候再运行Demo03后,会得到其栈内最大栈帧数为:3816 远小于原来的39317!
案例2:
public class Demo04 {
public static void main(String[] args) throws JSONProcessingException {
Dept d = new Dept();
d.setName("Market");
Emp e1 = new Emp();
e1.setName("csp");
e1.setDept(d);
Emp e2 = new Emp();
e2.setName("hzw");
e2.setDept(d);
d.setEmps(Arrays.asList(e1, e2));
// 输出结果:{"name":"Market","emps":[{"name":"csp"},{"name":"hzw"}]}
ObjectMapper mapper = new ObjectMapper();// 要导入jackson包
System.out.println(mapper.writeValueAsString(d));
}
}
class Emp {
private String name;
@jsonIgnore// 忽略该属性:为啥呢?我们来分析一下!
private Dept dept;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
class Dept {
private String name;
private List<Emp> emps;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
}
案例1:CPU占用过高
我们可以看到上图中的thread1 线程一直在运行(runnable)中,说明就是它占用了较高的CPU内存;
一些带有native 关键字的方法就是需要JAVA去调用本地的C或者c++方法,因为JAVA有时候没法直接和操作系统底层交互,所以需要用到本地方法!
如图:
这篇文章的内容就到这了,希望大家多多关注编程网的其他内容!
--结束END--
本文标题: JVM内存结构:程序计数器、虚拟机栈、本地方法栈
本文链接: https://lsjlt.com/news/128086.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0