专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

初入 JVM

96_1.png

1.堆

1.1 基本理论

1、 几乎所有的对象都存放在堆中
2、 Java 堆分为新生代和老年代,其中,新生代存放新生对象或者年龄比较小的对象,老年代存放老年对象或者比较大的对象
3、 将新生代细分的话,可以分为 eden , S0(from) , S1(to) , from 和 to 大小相等可以互换角色
4、 在绝大多数情况下,对象首先在 eden 空间分配,经历一次新生代回收后,若还存活则会进行 s0/s1,每经过一次回收则年龄+1,当对象年龄达到一定程序就会进入老年代

1.2 图解

96_2.png

96_3.png

1.3 代码解析

public class App{
    private int id;

    public App(int id){
        this.id = id;   
    }

    public void show() {
        System.out.println("My Id is " + id);   
    }

    public static void main(String args) {
        App a1 = new App(1);
        App a2 = new App(2);
        a1.show();
        a2.show();
    }
}

96_4.png

2.Java 栈

2.1 基本理论

1、 Java 栈是一块线程私有的内存空间
2、 是一块先进后出的数据结构,只支持出栈和入栈两个操作
3、 Java 栈中主要保存的是 栈帧 ,每一次函数调用都会对应生成一个栈帧
4、 当函数返回时,栈帧会从栈中移除,返回有两种,一种是执行到 return , 另一种是出现异常
5、 栈帧中主要包含的是:局部变量表,操作数栈,栈数据区
6、 Java 虚拟机提供 -Xss 来指定线程的最大栈空间

2.2 局部表量表

1、 主要存放的是:函数变量和局部变量
2、 局部表量表中的变量,只在当前函数调用中有用,当函数调用完毕后,函数栈帧被销毁,局表也会跟着被销毁
3、 如果函数参数或者局部变量过多,就会占用更多的栈空间,导致函数的嵌套调用次数减少
4、 可以使用 jclasslib 查看函数的局部变量表信息
5、 局部变量表中的变量也是重要的垃圾回收根节点,被局部变量表中直接或间接引用的对象是不会被回收的
6、 栈帧中的局部变量表中的槽位是可以复用的,从而达到了节约资源的作用

public void localv1() {
    byte[] a = new byte[6 * 1024 * 1024]; 
    Syste.gc();
}

v1 在申请内存空间后,调用 gc 进行回收,但是因为 a 指向了那块内存地址,因此无法对这块内存区域进行回收

public void localv2() {
    byte[] a = new byte[6 * 1024 * 1024];   
    a = null;
    System.gc();
}

a 时候指向那块区域,但是后面又将 a 设置为 Null ,导致没有了引用指向,因此可以对那快内存区域进行回收

public void localv3() {
    {
        byte[] a = new byte[6 * 1024 * 1024];   
    }
    System.gc();
}

a 虽然已经离开了作用范围,但是 a 依旧存在局部变量表中并且也指向这个 byte 数组,因此无法对这块内存区域进行回收

public void localv4() {
    {
        byte[] a = new byte[6 * 1024 * 1024];   

    }
    int c = 10;
    System.gc();
}

a 已经离开了作用范围,这时我们设置 c ,使得变量 c 复用了 a 的操作,导致了 byte 数组失去了引用,因此可以对这块内存区域进行回收

public void localv5() {
    localv1();
    System.gc();
}

v5 首先调用了 v1 , v1 调用完成后,v1 的栈帧就从栈中销毁了,因此v5可以对这块内存区域进行回收

2.3 操作数栈

1、 主要存放当前计算的中间结果,同时作为计算过程中变量的临时存储空间
2、 操作数栈也是一个先进后出的数据结构

2.4 栈数据区

1、 处了局部变量表和操作数栈,Java 栈还需要一些数据来支撑常量池解析,正常方法返回和异常处理等。

大部分 java 字节码指令需要进行常量池访问,在栈数据区内保存了访问常量池的指针,便于程序对常量池进行访问

1、 当函数发生异常时,虚拟机必须恢复调用者函数的栈帧,并让调用者函数继续执行,因此需要一个 ** 异常处理表 **

Excepetion  table :
from    to  target  type
  4     16    19     any
 19     21    19     any

它表示在字节码偏移量 4~16 字节可能抛出任意异常

当方法抛出异常时,虚拟机就会查找类似的异常表来进行处理,如果无法在异常表中找到合适的处理方法,则会结束当前函数调用,返回调用函数,并在调用函数中抛出相同的异常,并查找调用函数的异常表进行处理。

2.5 栈上分配

并不是所有的对象都在堆上分配

1、 它的基本思想是,对于那些线程私有的对象,可以将它们打散分配在栈上,而不是分配在堆上,分配在栈上的好处是可以在调用函数结束后就自行销毁,不需要垃圾回收器的介入,从而提升系统性能
2、 逃逸分析
3、 1. -server : 只有在 server 模式下才可以启动逃逸分析
2. -XX:+DoEscapeAnalysis :启用逃逸分析
3. -XX:+EliminatedAllocations :开启了标量替换(默认打开),允许将对象打散分配在栈上,会将对象中的字段以局部变量进行分配
4、 栈的空间相对较小,因此,大对象无法也不适合在栈上分配

3. 方法区(元数据区)

3.1 基本理论

1、 元数据区是一块线程共享的内存区域
2、 用于保存类的一些信息,比如字段,方法,常量池等
3、 可以使用 -XX:MaxMetaspaceSize 指定大小
4、 这是一块堆外的直接内存,默认情况下,虚拟机会好近所有可用的系统内存

文章永久链接:https://tech.souyunku.com/42815

未经允许不得转载:搜云库技术团队 » 初入 JVM

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们