双非本科准备秋招(9.3)—— JVM2

学这个JVM还是挺抽象的,不理解的东西我尽量记忆了,毕竟刚接触两天,也没遇到过实际应用场景,所以学起来还是挺费劲的,明天再补完垃圾回收这块的知识点。U•ェ•*U

先补一下JVM运行时的栈帧结构。

线程调用一个方法的执行和退出意味着一个栈帧的入栈和出栈,栈顶的栈帧叫当前栈帧,对应一个线程需要执行的最新的方法。其内部主要包含局部变量表、操作数栈、方法返回地址、动态链接等信息。

局部变量表(Local Variables Table)

用来存放方法参数和方法内部定义的局部变量。编译期就能确定局部变量表的容量,所以方法运行期间容量大小不会改变

容量大小以变量槽(Variable Slot)为单位,变量槽可以重用,这个局部变量使用完成了,它占用的内存就可以给别的变量使用了。

每个变量槽的大小是32位,所以64位的变量会用两个连续的槽,并且JVM不允许以任何方式访问其中的一个。

操作数栈

主要用于保存计算过程的中间结果,同时作为计算过程中变量的临时存储空间。

方法返回地址

**方法正常退出:**方法正常执行完成后,会将返回值返回给调用方法

**方法异常退出:**方法执行时发生了异常并且没有得到妥善处理,也会触发方法退出,并且不会有返回值返回给调用方。

方法正常退出,主调方法PC计数器的值就可以作为返回地址。方法的退出,就是栈帧出栈的过程。

动态链接

java源文件编译为字节码文件的过程中,所有的变量和方法会作为符号引用,保存在Class文件的常量池中。

当一个方法调用另一个方法时,就是通过常量池中指向方法的符号引用表示的。

动态链接就是能将符号引用 转换成调用方法的直接引用

比如我在main里写一个method_one()方法,编译过程中首先在常量池(Constant pool)创建该方法的符号引用,然后会执行invokestatic #2指令,这个指令就是通过常量池中的符号引用#2表示的,在运行时,动态链接会根据这个符号引用真正地调用这个方法。

垃圾回收Part1

四大引用

图解

先把黑马的图粘贴过来,众所周知四大天王有五位,四大引用有五个也是正常的。

HotSpot通过直接引用来访问java对象,根据引用强弱分为四种,**强软弱虚。**Strong、soft、weak、Phantom。

强引用

对象的一般状态都是强引用。

一个对象有强引用,GC绝不会回收。

java 复制代码
public class test {
    public static void main(String[] args) {
        String s = "sm";
        HashMap map = new HashMap();
    }
}

软引用

用于对象缓存,如果一个对象只有软引用,那么当内存不足,抛出OOM之前会回收软引用对象。

用法示例:

java 复制代码
public class GCAnalization {
    private static final int _8MB = 8 * 1024 * 1024;
    private static final int _4MB = 4*1024*1024;
    public static void main(String[] args) {
        ArrayList<SoftReference<byte[]>> list1 = new ArrayList<>();
        for(int i = 0; i < 10; i++){
            list1.add(new SoftReference<>(new byte[_4MB]));
        }
        for(int i = 0; i < 10; i++){
            System.out.println(list1.get(i));
        }
    }
}

弱引用

用于对象缓存,弱引用更低级,只要发生GC,弱引用就会被回收。

虚引用

好像没啥用,为对象设置一个虚引用,该对象被回收时能收到系统通知,必须与引用队列关联使用。

判断对象是否能回收的算法

引用计数法

当对象被引用一次,加1,不被引用,减1。

但是可能出现循环引用,这时就会发生内存泄露。

可达性分析

通过一系列GC Root(根对象节点)对象作为起点,根据引用关系,向下搜索,能找到的对象就是可达的,表示不可回收。

什么对象能作为GC Root?

比如:

1、虚拟机栈中引用的对象

2、方法区中类静态属性引用的对象

3、本地方法栈的Native对象

等等。

垃圾回收算法

标记清除

找出所有存活的对象,对存活的对象进行标记,清除未被标记的对象。

速度快,但会产生内存碎片。

标记整理

找出所有对象,对存活的对象进行标记,将存活对象整理到一端(紧凑),然后清除未被标记的对象。

没有内存碎片,速度慢

复制

划分两个大小相同的区域,每次只用一块,这块用完了,就把存活的对象复制到另一块,然后清理内存空间。这样交替使用两块内存。

没有内存碎片,占用空间大。

相关推荐
yanjiaweiya16 分钟前
云原生-集群管理
java·开发语言·云原生
gadiaola24 分钟前
【JavaSE面试篇】Java集合部分高频八股汇总
java·面试
艾迪的技术之路1 小时前
redisson使用lock导致死锁问题
java·后端·面试
今天背单词了吗9801 小时前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师1 小时前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构1 小时前
订单初版—2.生单链路中的技术问题说明文档
java
咖啡啡不加糖2 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南2 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
DKPT2 小时前
Java享元模式实现方式与应用场景分析
java·笔记·学习·设计模式·享元模式