java类加载

一、加载简单java对象 

编写一个类,不依赖任何其他jar,如下

package cc.eslink.bigscreen.controller.config;

/**
 * @Author : wangbin
 * @Date : 2022/1/21 11:29
 * @Description:
 */
public class User {
    private String name;

    public User() {
        System.out.println("create User!!!");
    }

    public void setName(String name){
        this.name=name;
    }

    public String getName(){
        return this.name;
    }
}

打成jar包,切记,一定打成原生jar包,不是胖jar

 /**
     * 经过一天的尝试,终于把类加载跑通了,之前失败N次的原因也找到了
     * 说来让人心酸,就是因为之前生成的胖jar包跟原生jar包格式不同
     * 使用类加载就要使用标准jar
     * @param args
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws IOException
     */
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
        File file = new File("D:\\tlpi\\jar\\bigscreen-standard.jar");
        String className = "cc.eslink.bigscreen.controller.config.User";
        URL url = file.toURI().toURL();
        URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader());
        Class<?> aClass = classLoader.loadClass(className);
        aClass.newInstance();


    }

 输出:

create User!!!

二、加载一个依赖其他类的class

我们知道在编程中完全不依赖第三方jar基本上是不可能的,那么我们的URLClassLoader能加载这些类吗?答案是可以

我构造了一个新类,它有一些依赖的包

package com.example.api.client.config;

import com.example.api.gateway.exception.CachedException;
import com.example.api.gateway.exception.FailedException;
import com.example.api.gateway.filter.AbstractFilter;
import com.example.api.gateway.handler.HttpMessage;

/**
 * @Author : wangbin
 * @Date : 2022/1/21 14:38
 * @Description:
 */
public class ThirdFilter extends AbstractFilter {
    @Override
    public HttpMessage filter(HttpMessage request) throws FailedException, CachedException {
        System.out.println("I am ThirdFilter");
        return null;
    }
}

我们在加载一次

 public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
        File file = new File("D:\\tlpi\\jar\\bigscreen-standard.jar");
        String className = "com.example.api.client.config.ThirdFilter";
        URL url = file.toURI().toURL();
        URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader());
        Class<? extends AbstractFilter> aClass =( Class<? extends AbstractFilter>) classLoader.loadClass(className);
        AbstractFilter filter = aClass.newInstance();
        try {
            filter.filter(null);
        } catch (FailedException e) {
            e.printStackTrace();
        } catch (CachedException e) {
            e.printStackTrace();
        }
    }

输出:I am ThirdFilter

成功了,的确,但成功的很侥幸,因为ThirdFilter依赖的类恰好都在我们的JVM中,如果不在会怎样?

三、加载一个依赖其他第三方我们不知道的jar的class

为了验证我之前的猜测,我再ThirdFilter中加入一个我们现有环境中没有用过的类,代码如下:

package com.example.api.client.config;

import com.example.api.gateway.exception.CachedException;
import com.example.api.gateway.exception.FailedException;
import com.example.api.gateway.filter.AbstractFilter;
import com.example.api.gateway.handler.HttpMessage;
import org.jdom.Document;
/**
 * @Author : wangbin
 * @Date : 2022/1/21 14:38
 * @Description:新加入org.jdom.Document
 */
public class ThirdFilter extends AbstractFilter {
    @Override
    public HttpMessage filter(HttpMessage request) throws FailedException, CachedException {
        String simpleName = Document.class.getSimpleName();
        System.out.println(simpleName);
        System.out.println("I am ThirdFilter");
        return null;
    }
}

我们依然按照之前的方式进行类加载,不出所料,失败了

Exception in thread "main" java.lang.NoClassDefFoundError: org/jdom/Document
    at com.example.api.client.config.ThirdFilter.filter(ThirdFilter.java:16)
    at com.example.api.gateway.utils.LoadUtil.main(LoadUtil.java:54)
Caused by: java.lang.ClassNotFoundException: org.jdom.Document
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 2 more

因为jvm中根本没有这个类的class,我们也没有告诉系统他的jar包在哪里。

那么是不是我告诉系统这个jar包在哪里,他就能帮我找到,我修改了类加载的方法

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
        File file = new File("D:\\tlpi\\jar\\bigscreen-standard.jar");
        String className = "com.example.api.client.config.ThirdFilter";
        URL url = file.toURI().toURL();
        File file1 = new File("D:\\tlpi\\jar\\jdom-1.1.3.jar");
        URL url1 = file1.toURI().toURL();
        URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url1}, Thread.currentThread().getContextClassLoader());
        Class<? extends AbstractFilter> aClass =( Class<? extends AbstractFilter>) classLoader.loadClass(className);
        AbstractFilter filter = aClass.newInstance();
        try {
            filter.filter(null);
        } catch (FailedException e) {
            e.printStackTrace();
        } catch (CachedException e) {
            e.printStackTrace();
        }
    }

输出:

Document
I am ThirdFilter

成功了,证明我们的推测是正确的!

posted @ 2022-01-21 14:32  Mars.wang  阅读(63)  评论(0编辑  收藏  举报