JVM

3 篇文章 0 订阅
3 篇文章 0 订阅

JVM内存结构

Java虚拟机由 类加载子系统、执行引擎、JVM运行时数据区 构成
虚拟机结构

运行分析

每个线程都有自己私有的数据区,如下图
举例
方法用入栈的方式调用
例

代码调试例子

public class HelloWorld {

    public int add() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 100;
        return c;
    }

    /**
     * 程序入口
     * @param args
     */
    public static void main(String[] args) {
        HelloWorld app = new HelloWorld();
        int result = app.add();
        System.out.println(result);
    }

}

例

javap

因为.class文件是经过编译的,所以我们无法看懂,我们想看它怎么办呢?通过借助javap帮忙
javap
通过javap -c 加上.class文件名,也可以通过javap -c 文件名.class > 文件名.txt 写入文本文件
例
虽然借助工具编译之后,我们大概的结构可以看懂了,但是细节还是看不懂,可以去官方网站找到这些指令的含义

iconst_1 将int类型常量1压入栈
iconst_2 将int类型常量2压入栈
istore_1 将int类型值存入局部变量1
istore_2 将int类型值存入局部变量2
istore_3 将int类型值存入局部变量3
iload_1 从局部变量1中装载int类型值
iload_2 从局部变量2中装载int类型值
iload_3 从局部变量3中装载int类型值
iadd 执行int类型的加法
biputsh 将一个8位带符号整数压入栈
imul 执行int类型的乘法
ireturn 从方法中返回int类型的数据

分析add()方法

istore

istore
执行istore_2的时候也和1一样
2

iload_1

把1在压回栈中; iload_2 把2也压回栈中
入栈

iadd

在哪里执行?执行引擎操作 操作数栈 在栈里执行
1和2出栈执行iadd方法相加,获得3,入栈
iadd

biputsh

7: bipush 100
9: imul

仔细看的话会发现 中间没有8,因为7中是包含了8,100就是8
把100压入栈
100入栈

imul

100和3出栈执行imul,结果入栈
imul

istore_3/iload_3

将300赋值给第三个变量,将300压入栈

ireturn

从方法出口返回数值
返回
对象变量也是入栈,它的引用在堆中
堆

程序计数器

程序计数器:指向当前线程所执行的字节码指令的(地址)行号
Code代表的就是行号,程序计数器加1,就执行一条命令
行号

本地方法栈

public static native void sleep(long millis) throws InterruptedException;

如被native修饰的方法,就存储在本地方法栈中

方法区(元空间)

线程共享,存放已经被虚拟机加载进来的类信息,常量、静态变量,JIT编译后的数据代码。java的class文件首先进入的到方法区里面去

对象与类的关系
对象与类的关系

堆分为两部分,新生代和老年代
新生代又分为三部分 Eden; from; to
对象的创建大部分都是在Eden区

堆结构图

堆结构图

比例

新生代: 老年代 = 1: 2
Eden: from: to = 8: 1: 1

垃圾回收GC

-XX:MaxTenuringThreshold=15超过15次进入老年代
-XX:PretenureSizeThreshold= M设置超过这个值的直接进入老年代

minor gc

当Eden区内存被占满之后就会触发,minor gc
根的可达性判定 gc roots,根据当前已创建的对象进行判定,判定这个对象是否被其他地方调用,如果没有被调用就标记成游离状态(说明是可以被回收的),那么就会被回收掉。
剩下的没被回收的,会进入到from区,并且age+1
当再次进行minor gc的时候,已经进入from区且还被继续调用的age继续+1,没被调用的就会被回收,新进来的和原有的从from区进入to区,to区变成from区,from区变成to区。
当这种from区和to区变换age>=15的时候,就会进入到老年代区

full gc

晋升到老年代的两种条件:

  1. age >= 15
  2. 在survivor区中,所有年龄的对象的所占空间的累加和大于survivor空间的一半,大于或等于该年龄的对象,都可以进入老年代。

如同上面所说,age>=15的会进入老年代区,但老年代区也是有空间限制的,当老年代空间满了的时候,就会触发full gc,会出现STW的现象(stop the work)。

面试题

为什么Java需要性能调优?

在有限的空间做无限的事情,如果没有Java性能调优,每创建一个对象都需要占用内存,用完之后没有引用的对象,不被回收,那么它还继续占用内存空间,直到占用了所有内存空间的时候,就会保错,内存不够;有Java性能调优,就会把无用的垃圾,及时回收,释放更多的内存空间,提供给其他使用。

为什么Java需要采用分代回收思想?

让更少的对象进入老年代,减少STW次数,提高性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值