java new对象的类加载器是谁?

Posted master-dragon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java new对象的类加载器是谁?相关的知识,希望对你有一定的参考价值。

关于java new 对象使用的流程我们都知道如下图所示:

注:图片来自网络

但是究竟是谁(即哪个类加载器)完成【加载】的呢?

如下两个类:

  • Test
package com.hotload;

/**
 * @Author mubi
 * @Date 2020/7/27 08:49
 */
public class Test {

    public Test() {
    }

    public String hello(String msg){
        return "hello:" + msg;
    }

    public Test2 getTest2(){
        return new Test2();
    }
}

  • Test2
package com.hotload;

/**
 * @Author mubi
 * @Date 2020/7/27 08:49
 */
public class Test2 {

    public Test2() {
    }

    public String hello2(){
        return "test2";
    }

}

普通java程序下,都是sun.misc.Launcher$AppClassLoader加载的

当使用自定义类加载器获取Test2对象就发现不同了
即不同的地方new同样的对象(Test2在不同的地方new的),结果是不同的;都是new,但是使用的类加载器是不同的


附code:

public static void main(String[] args) throws Exception {
    String rootPath = "/Users/mubi/git_workspace/java8/java8-api/src/main/java";
    MyComOtherClassLoader myClassLoader = new MyComOtherClassLoader();
    myClassLoader.path = rootPath;

    Class clz = Class.forName("com.hotload.Test", true, myClassLoader);
    Object test = clz.newInstance();
    System.out.println(test.getClass().getClassLoader());

    Method method = clz.getMethod("getTest2");

    Object test2 = method.invoke(test);
    System.out.println(test2.getClass().getClassLoader());
}
package com.hotload;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @Author mubi
 * @Date 2019/3/20 10:54 PM
 */
public class MyComOtherClassLoader extends ClassLoader {
    public String path;
    public String packageName;
    public String className;

    public MyComOtherClassLoader() {
        super(ClassLoader.getSystemClassLoader());
    }

    private String classNameToPath() {
        // 得到类文件的URL
        return path + "/" + packageName.replace('.', '/')
                + "/"
                + className + ".class";
    }

    @Override
    public Class loadClass(String name) throws ClassNotFoundException {
        // 非 com.hotload package下面的类,都用默认的加载,否则用自定义的加载方法
        if (!name.contains("com.hotload")) {
            // 是否已经被加载
            Class loadedClass = findLoadedClass(name);
            if (loadedClass == null) {
                // 用父类去加载该类
                loadedClass = getParent().loadClass(name);
                return loadedClass;
            } else {
                return loadedClass;
            }
        }


        int i = name.lastIndexOf('.');
        packageName = "";
        if (i != -1) {
            packageName = name.substring(0, i);
//            System.out.println("package: " + packageName);
            className = name.substring(i + 1);
//            System.out.println("class name: " + name);
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPackageAccess(packageName);
            }
        }
        //依然调用父类的方法
//        return super.loadClass(name);
        return this.findClass(name);
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {
        int i = name.lastIndexOf('.');
        packageName = "";
        if (i != -1) {
            packageName = name.substring(0, i);
//            System.out.println("package: " + packageName);
            className = name.substring(i + 1);
//            System.out.println("class name: " + name);
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPackageAccess(packageName);
            }
        }
        Class<?> clazz = this.findLoadedClass(name); // 父类已加载
        if(null != clazz){
            return clazz;
        }

//        System.out.println("findClass param name: " + name);
        byte [] b = this.getClassBytes();
//        System.out.println("b len:" + b.length);
        clazz=defineClass(null, b, 0, b.length);
        return clazz;
    }
    public byte[] getClassBytes() {
        String classPath = classNameToPath();
//        System.out.println("classPath:" + classPath);
        File file=new File(classPath);
        try(FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream bos=new ByteArrayOutputStream();) {
            byte[] b=new byte[1024*2];
            int n;
            while((n=fis.read(b))!=-1){
                bos.write(b, 0, n);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

以上是关于java new对象的类加载器是谁?的主要内容,如果未能解决你的问题,请参考以下文章

java new对象的类加载器是谁?

Java双亲委派模型

java new一个对象的过程

Java对象创建过程

java new一个对象的过程中发生了什么

new一个对象的过程