双非本科准备秋招(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绝不会回收。

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

软引用

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

用法示例:

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对象

等等。

垃圾回收算法

标记清除

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

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

标记整理

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

没有内存碎片,速度慢

复制

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

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

相关推荐

  1. 本科准备(11.2)—— 力扣字符串

    2024-01-29 07:08:01       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-29 07:08:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-29 07:08:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-29 07:08:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-29 07:08:01       20 阅读

热门阅读

  1. Asp.net Core Mvc 7.0 Web 控制器接收Get/Post表单参数

    2024-01-29 07:08:01       27 阅读
  2. 【笔记】Helm- 5 Chart模板指南-3 Values文件

    2024-01-29 07:08:01       36 阅读
  3. ubuntu 安装node和npm

    2024-01-29 07:08:01       30 阅读
  4. Xlua分析:Lua调用C#

    2024-01-29 07:08:01       32 阅读
  5. 闲聊电脑(2)常见零部件

    2024-01-29 07:08:01       36 阅读