如下图
整段代码如下,当注释掉myThread.setContextClassLoader(myClassLoader);
后才正常运行
package com.hotload;
import java.util.ServiceLoader;
class MyThread extends Thread{
@Override
public void run() {
try{
ServiceLoader<A> serviceLoader = ServiceLoader.load(A.class);
A a = serviceLoader.iterator().next();
a.say();
} catch (Exception e){
}
}
}
/**
* @Author mubi
* @Date 2021/9/25 15:29
*/
public class Application {
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;
MyThread myThread = new MyThread();
myThread.setContextClassLoader(myClassLoader);
myThread.start();
}
}
要知道错误,首先要理解java spi,serviceload是用线程上线文加载器的,我们debug到报错代码:接口A的类加载器和接口A的实现类Aimp1的类加载器是不同的,因为设置了线程上线文:
当代码改成如下后正常运行
package com.hotload;
import java.lang.reflect.Method;
import java.util.ServiceLoader;
class MyThread extends Thread{
@Override
public void run() {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazzA = cl.loadClass("com.hotload.A");
ServiceLoader<A> serviceLoader = ServiceLoader.load(clazzA);
Object aimp1 = serviceLoader.iterator().next();
Method method = aimp1.getClass().getMethod("say");
method.invoke(aimp1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* @Author mubi
* @Date 2021/9/25 15:29
*/
public class Application {
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;
MyThread myThread = new MyThread();
myThread.setContextClassLoader(myClassLoader);
myThread.start();
}
}
debug 查看如下(java.util.ServiceLoade
的 375行 可以走完,不再fail了)