内构函数java_图灵学院笔记-java虚拟机底层原理

Table of Contents generated with DocToc

笔记来源:图灵学院

一、java虚拟机概述

java虚拟机用于将字节码文件.class转化为不同操作系统上的机器码

21eaf01b79e7ca6c13154f0c733b04e4.png

java虚拟机的内存模型

55707da4e30e2e81224d1edb476c5cea.png

二、栈内存解析

2.1 概述

java虚拟机为每一个java线程分配一个栈内存空间,存放变量

public class Math{

public static final int initData = 666;//常量存储在方法区

public int compute() { //一个方法对应一块栈帧内存区域

int a=1;

int b=2;

int c = (a+b)*10;

return c;

}

public static void main(String[] args){

Math math = new Math();

math.compute();

}

}

a,b,c 保存在main线程的compute()栈帧中

d6bd25c57d2f061330a0d033da127b65.png

2.2 栈帧内部结构

学习栈帧内部结构前,我们首先要阅读字节码文件。

javac Math.java

javap -c Math.class > Math.txt

打开生成的Math.txt,可以看到反汇编后的代码如下:

Compiled from "Math.java"

public class jvm.Math {

public static final int initData;

public jvm.Math();

Code:

0: aload_0

1: invokespecial #12 // Method java/lang/Object."":()V

4: return

public int compute();

Code:

0: iconst_1

1: istore_1

2: iconst_2

3: istore_2

4: iload_1

5: iload_2

6: iadd

7: bipush 10

9: imul

10: istore_3

11: iload_3

12: ireturn

public static void main(java.lang.String[]);

Code:

0: new #1 // class jvm/Math

3: dup

4: invokespecial #25 // Method "":()V

7: astore_1

8: aload_1

9: invokevirtual #26 // Method compute:()I

12: pop

13: return

}

2.2.1 我们来解析一下compute()里面的代码:

public int compute() { //一个方法对应一块栈帧内存区域

int a=1;

int b=2;

int c = (a+b)*10;

return c;

}

//=======================================

public int compute();

Code:

0: iconst_1//将常量1压入操作数栈

1: istore_1 //将int类型的值存入局部变量1 -- a

2: iconst_2 //将常量2压入操作数栈

3: istore_2 //将int类型的值存入局部变量2 -- b

4: iload_1//从局部变量1装载int类型的值

5: iload_2 //从局部变量2装载int类型的值

6: iadd//1+2

7: bipush 10

9: imul//*10

10: istore_3//将int类型的值存入局部变量3 -- c

11: iload_3//装载c的值

12: ireturn

赋值过程:

f907d33f9cc951cf56adf1d91392410c.png

装载,执行过程(操作数栈:临时存储需要操作的值):

a411bf4a45b6e3faab31e06a8d86fb7d.png

2.2.2 main函数内存区域

​main中存储了一个math对象的指针,指向堆(堆中有为这个对象开辟的内存空间):

0eb3b90d8030c43bc9e52a6dbb1e4be0.png

三、本地方法栈

早期 JAVA 需要与C/C++进行交互,所以用本地方法栈存储C/C++方法

ce2791cf4c6a4c93131c10554fd6c5be.png

四、堆

首先我们看看堆的结构:

e2a99836d81058bc718b0386fff454a0.png

​堆假设只有600M的话,那么年轻代占了1/3,也就是200M,老年代占了2/3。最开始的时候,对象都存放在Eden(伊甸区)中。

​当Eden区装满时,则字节码执行引擎开启一个线程,运行minor gc,扫描伊甸区中的对象,如果对象被引用了,则在s0区中复制一份,否则留在Eden中,被垃圾回收机制清理。

​其他区域也是类似的处理(在Eden,s0,s1中移动时,“年龄“会加大,当达到15时,会转入老年区,controller、service、bean、数据库持久层、缓存都是常见的老年区对象):

e5e2b16b84ccc5278a2dd38d919525b8.png

​当老年代区放满后,字节码执行引擎开启一个线程,运行full gc,对所有区域进行垃圾回收,减少堆的空间,但是老年区被引用的对象还是不会被回收,所以当老年区再次被放满溢出时,会触发OutOfMemoryError的异常,即java堆不够用了。

扩展:STW【stop the world】,当 JVM 调用gc清理堆时,会暂停掉所有用户程序,比如电商购物时,点击按钮后通常会卡顿一下

垃圾回收,减少堆的空间,但是老年区被引用的对象还是不会被回收,所以当老年区再次被放满溢出时,会触发OutOfMemoryError的异常,即java堆不够用了。

扩展:STW【stop the world】,当 JVM 调用gc清理堆时,会暂停掉所有用户程序,比如电商购物时,点击按钮后通常会卡顿一下

所以 JVM 调优就是:尽量想方设法减少 STW 时间

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值