类加载机制和finalize方法-第九章

系列文章目录

第一章 ArrayList-Java八股面试(一)

第二章 HashMap-Java八股面试(二)

第三章 单例模式-Java八股面试(三)

第四章 线程池和Volatile关键字-Java八股面试(四)

第五章 ConcurrentHashMap-Java八股面试(五)

第六章 spring之refresh流程-Java八股面试(六)

第七章 Spring Bean生命周期七大阶段-Java八股面试(七)

第八章 JVM内存模型和垃圾回收机制-第八章


动态每日更新算法题,想要学习的可以关注一下

文章目录

  • 系列文章目录
  • 一、类加载过程和双亲委派
    • 1.1 加载器
    • 1.2 双亲委派的工作流程
    • 1.3 双亲委派的目的
    • 1.4 能否自己写个System类来避免双亲委派
  • 二、 对象引用和回收
    • 2.1 强引用
    • 2.2 软引用
    • 2.3 弱引用
    • 2.4 虚引用
    • 2.5 finalize的介绍
    • 2.6 执行finalize的时机
    • 2.7 finalize的缺点


一、类加载过程和双亲委派

Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制。
Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能,这里就是我们经常能见到的Class类。

需要特地说明的是懒惰执行和之前在单例模式中提到的懒汉式一样,只有用到了该类时才会进行加载。
类加载机制和finalize方法-第九章_第1张图片

1.1 加载器

类加载机制和finalize方法-第九章_第2张图片

1)启动类加载器(Bootstrap ClassLoader):负责加载JAVA_HOME\lib目录中并且能被虚拟机识别的类库到JVM内存中,如果名称不符合的类库即使放在lib目录中也不会被加载。该类加载器无法被Java程序直接引用。
2)扩展类加载器(Extension ClassLoader):该加载器主要是负责加载JAVA_HOME\lib\,该加载器可以被开发者直接使用。
3)应用程序类加载器(Application ClassLoader):该类加载器也称为系统类加载器,它负责加载用户类路径(Classpath)上所指定的类库,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
4)我们的应用程序都是由这三类加载器互相配合进行加载的,我们也可以加入自己定义的类加载器。
从上到下为父->子的关系

1.2 双亲委派的工作流程

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。

1.3 双亲委派的目的

在这里插入图片描述

1.4 能否自己写个System类来避免双亲委派

在源码中可以看到这里会有一个安全检查,来查看你的包是否是以java开头,所以编译就不会通过。
类加载机制和finalize方法-第九章_第3张图片

二、 对象引用和回收

类加载机制和finalize方法-第九章_第4张图片

2.1 强引用

强引用是最常见的,一个变量用等号赋值,就是把这个变量指向强引用。只要有强引用,GC 永远不会回收掉该对象。

2.2 软引用

软引用引用的对象,虽然是可达的(存活的),但是在 GC 回收的时候,会考量这些对象。当 GC 认为内存还足够,那么就不回收这些对象了,但是当 GC 认为内存紧缺不够的时候,会强行回收这些对象。
软引用需要借助 SoftReference 类来实现,下面的代码创建了一个软引用,并使用它。

SoftReferencesr = new SoftReference(new String("hello"));
System.out.println(sr.get());

2.3 弱引用

弱引用和软引用类似,对象都是可达的,但仍然会被 GC 回收。不同点在于,弱引用只要 GC 开始,就会被回收,而软引用只有当 JVM 内存空间不足的时候才会被回收。
弱引用的需要 WeakReference 类来实现。

WeakReferencesr = new WeakReference(new String("hello"));
System.out.println(sr.get());
System.gc(); //通知JVM的gc进行垃圾回收
System.out.println(sr.get());

需要说明的是,第二次输出结果是null,所以gc回收的是弱引用关联的对象而不是sr对象本身(强引用)。

2.4 虚引用

虚引用也称为幽灵引用或幻影引用。虚引用的 get 方法永远返回 null,一个对象是否存在虚引用不会对生存时间构成影响。唯一的用处:能在对象被 GC 时能够得知。JAVA 中用 PhantomReference 来实现虚引用。PhantomReference 使用时,必须要关联一个 ReferenceQueue 对象。当一个对象被 GC 的时候,如果该对象有虚引用,那么就会把对象放入 ReferenceQueue 里。通过检查 ReferenceQueue 队列中的对象来判等对象是否即将被回收,可以记录一些日志之类的信息。

ReferenceQueue queue = new ReferenceQueue();
PhantomReferencepr = new PhantomReference(new String("hello"), queue);
System.out.println(pr.get());

2.5 finalize的介绍

类加载机制和finalize方法-第九章_第5张图片

需要说明的是执行finalize方法的线层是一个守护线程,当主线程执行完时即使守护线程还没有执行完也会自动关闭,所以会造成oom的情况。

2.6 执行finalize的时机

当重写了finalize之后,守护线程会创建两个队列。

下图用到了虚引用的概念

2.7 finalize的缺点

你可能感兴趣的:(java,jvm,面试)