类卸载

BytePioneer
• 阅读 1015
package study;

import java.net.URL;
import java.net.URLClassLoader;
/*
    由Java虚拟机自带的类加载器所加载的类,在虚拟机的生命周期中,始终不会被卸载,
    Java虚拟机自带的类加载器包括根类加载器、扩展类加载器和系统类加载器。
   Java虚拟机本身会始终引用这些类加载器,而这些类加载器则会始终引用它们所加载的类的Class对象,
     因此这些Class对象始终是可触及的。
   由用户自定义的类加载器加载的类是可以被卸载的。
    jvm参数-verbose:class 即可看到类的加载和卸载信息
 */
/*
卸载类满足的条件
    1、class所有实例被回收
    2、class类没有别引用
    3、class的加载器实例被回收
 */
public class StudyMain {
    public static void main(String[] args) throws Exception {
        new StudyMain().solve();
        Thread.sleep(5000);
        System.gc();
        Thread.sleep(5000);
    }

    public void solve() {
        /*
         path不以’/'开头时,默认是从此类所在的包下取资源;
         path以’/'开头时,则是从ClassPath根下获取;
         this.getClass().getResource("").getPath();
         */
        // 这个路径 <= appClassLoader所负责的路径,因为双亲委托的机制
        String path = "/D:/gitHome/asmStudy/target/classes/";
        try {
            // 这里一定要加file: 表示协议
            ClassLoader loader1 = new URLClassLoader(new URL[]{new URL("file:" + path)});
            // 类名要写全
            Class t =  loader1.loadClass("instrumentation.TransClass");
            t = null;
            loader1 = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

当类加载器重写了finalize

package study;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class MyClassLouder extends ClassLoader {
    public static void main(String[] args) throws Exception {
        String path = "D:\\Users\\YEZHENGWU839\\Desktop\\xiaoxi\\";
        MyClassLouder other = new MyClassLouder(path, "other");
        Class.forName("MethodAccessor.TestLoad", true, other);
        other = null;
        Thread.sleep(5000);
        System.gc();
        Thread.sleep(5000);
        // 第一次gc卸载不掉类是因为finalize线程优先级比较低 所以回收的时候
        // other的 finalize 对象还没有被finalize线程清理
        // 所以other并没有回收,所以类也就卸载不了
        System.out.println("第一次 gc 结束 第二次开始");
        System.gc();
        Thread.sleep(5000);
    }

    private String classpath;
    private String name;
    // 重写finalize方法 一般不重写这个 影响gc
    @Override
    protected void finalize() throws Throwable {
        System.out.println("MyClassLoader finalize");
    }

    public MyClassLouder(String classpath, String name) {
        this.classpath = classpath;
        this.name = name;
    }

    public MyClassLouder(String classpath, String name, ClassLoader parent) {
        super(parent);
        this.classpath = classpath;
        this.name = name;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
       try {
            byte[] bin = Files.readAllBytes(Paths.get(classpath + name.replace(".", "/") + ".class"));
            return defineClass(bin, 0, bin.length);
        } catch (IOException e) {
            throw new ClassNotFoundException();
        }
    }
}
点赞
收藏
评论区
推荐文章
灯灯灯灯 灯灯灯灯
4年前
图文详解,史上最全【类加载子系统】解说!!
内存结构概述简图详细图英文版中文版注意:方法区只有HotSpot虚拟机有,J9,JRockit都没有如果自己想手写一个Java虚拟机的话,主要考虑哪些结构呢?1.类加载器2.执行引擎类加载器子系统类加载器子系统作用:1.类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。2.ClassLo
Wesley13 Wesley13
3年前
java类的加载与加载器
java代码在计算机中经历的三个阶段:1.Source源代码阶段(代码还是在硬盘上,并没有进入内存)  Student.java通过javac编译Student.class字节码文件2.类加载器ClassLoader将字节码文件加载进入内存,成为Class类对象(成员变量Field\\fields、构造方法Const
Wesley13 Wesley13
3年前
Java高级篇——深入浅出Java类加载机制
类加载器简单讲,类加载器ClassLoader的功能就是负责将class文件加载到jvm内存。类加载器分类从虚拟机层面讲分为两大类型的类加载器,一是BootstrapClassloader即启动类加载器(C实现),它是虚拟机的一部分,二是其他类型类加载器(JAVA实现),在虚拟机外部,并全部继
Stella981 Stella981
3年前
Jvm类的加载机制
1.概述虚拟机加载Class文件(二进制字节流)到内存,并对数据进行校验、转换解析和初始化,最终形成可被虚拟机直接使用的Java类型,这一系列过程就是类的加载机制。2.类的加载时机类从被虚拟机加载到内存开始,直到卸载出内存为止,整个生命周期包括:加载——验证——准备——解析——初始化——使用——卸载这7个阶段。其中验
Wesley13 Wesley13
3年前
Java类加载机制
启动(Bootstrap)类加载器启动类加载器主要加载的是JVM自身需要的类,这个类加载使用C语言实现的,是虚拟机自身的一部分,它负责将<JAVA\_HOME/lib路径下的核心类库或Xbootclasspath参数指定的路径下的jar包加载到内存中,注意必由于虚拟机是按照文件名识别加载jar包的,如rt.jar,如果文件名不被虚拟机
Wesley13 Wesley13
3年前
Java虚拟机类加载机制
概述  虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。  与那些在编译时需要进行连接工作的语言不同,在Java语言里面,类型的加载、连接和初始化过程都在程序运行期间完成的,这种策略虽然会稍微增加一些系统性能开销,但是会为Java应用程序
Stella981 Stella981
3年前
Android动态加载之ClassLoader详解
Dalvik虚拟机如同其他Java虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。而在Java标准的虚拟机中,类加载可以从class文件中读取,也可以是其他形式的二进制流。因此,我们常常利用这一点,在程序运行时手动加载Class,从而达到代码动态加载执行的目的。只不过Android平台上虚拟机运行的是Dex字节码,一种对class文件优化的产物
Stella981 Stella981
3年前
JVM(四)JVM的双亲委派模型
1、两种不同的类加载器  从JAVA虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器(BootstrapClassLoader),这个类加载器使用C语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些加载器都由Java语言实现,独立于虚拟机外部,并且全都继承自抽象类java,lang.ClassLoader。
Stella981 Stella981
3年前
JVM(Java SE 11版本)加载类和接口
本文介绍了Java虚拟机(JavaSE11版本)加载类和接口。加载类和接口加载是指查找具有特定名称的类或接口类型的二进制形式的过程。典型的做法是,查找事先由Java编译器从源代码计算而来二进制表示,但也可能是通过动态计算。二进制形式最终会构造成一个Class对象。加载的精确语义在JavaJavaMachineSpecif
Java类加载机制详解 | 京东云技术团队
一.类加载器及双亲委派机制|类加载器|加载类|备注||||||启动类加载器(BootstrapClassLoader)|JAVAHOME/jre/lib|无上级,无法直接访问由jvm加载||拓展类加载器(ExtensionClassLoader)|JAVA
BytePioneer
BytePioneer
Lv1
载着我满满的怀念,你渐行渐远。
文章
4
粉丝
0
获赞
0