Java 中,实现共享动态加载的类实例在多个环境(如 Java 应用程序和 JShell 实例)之间,需要一些特别的设置。这通常涉及到自定义类加载器、反射以及在不同的上下文中动态加载类。本文主要介绍Java中,JShell中加载的classes与主程序中的共享。

1、重写findClass()方法

创建一个定制的LoaderDelegate实现,它提供已经加载的类的实例,而不是再次加载它们。使用默认实现DefaultLoaderDelegate (source) 并覆盖其内部RemoteClassLoaderfindClass方法:

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
    byte[] b = classObjects.get(name);
    if (b == null) {
        Class<?> c = null;
        try {
            c = Class.forName(name);//使用自定义方法加载类
        } catch(ClassNotFoundException e) {
        }
        if(c == null) {
            return super.findClass(name);
        }
        return c;
    }
    return super.defineClass(name, b, 0, b.length, (CodeSource) null);
}

2、创建JShell instance(实例)

JShell shell = JShell.builder()
    .executionEngine(new ExecutionControlProvider() {
        @Override
        public String name() {
            return "name";
        }
        @Override
        public ExecutionControl generate(ExecutionEnv ee, Map<String, String> map) throws Throwable {
            return new DirectExecutionControl(new CustomLoaderDelegate());
        }
    }, null)
    .build();
shell.addToClasspath("Example.jar");//将自定义类添加到类路径,否则无法在JShell中引用它们