请查看下面的修改
我正在尝试创建一个 JShell实例 ,该 实例 使我可以访问它,并让我与创建它的 JVM中的
对象进行交互。这对于在编译时可用的类很好,但对于 动态 加载的类却失败了。
public class Main {
public static final int A = 1;
public static Main M;
public static void main(String[] args) throws Exception {
M = new Main();
ClassLoader cl = new URLClassLoader(new URL[]{new File("Example.jar").toURL()}, Main.class.getClassLoader());
Class<?> bc = cl.loadClass("com.example.test.Dynamic");//Works
JShell shell = JShell.builder()
.executionEngine(new ExecutionControlProvider() {
@Override
public String name() {
return "direct";
}
@Override
public ExecutionControl generate(ExecutionEnv ee, Map<String, String> map) throws Throwable {
return new DirectExecutionControl();
}
}, null)
.build();
shell.eval("System.out.println(com.example.test.Main.A);");//Always works
shell.eval("System.out.println(com.example.test.Main.M);");//Fails (is null) if executionEngine is not set
shell.eval("System.out.println(com.example.test.Dynamic.class);");//Always fails
}
}
另外,DirectExecutionControl
与交换可以LocalExecutionControl
得到相同的结果,但是我不理解两个类之间的区别。
如何使 运行时 加载的类可用于此 JShell实例 ?
编辑:此问题的第一部分已解决,下面是更新的源代码,以演示问题的第二部分
public class Main {
public static void main(String[] args) throws Exception {
ClassLoader cl = new URLClassLoader(new URL[]{new File("Example.jar").toURL()}, Main.class.getClassLoader());
Class<?> c = cl.loadClass("com.example.test.C");
c.getDeclaredField("C").set(null, "initial");
JShell shell = JShell.builder()
.executionEngine(new ExecutionControlProvider() {
@Override
public String name() {
return "direct";
}
@Override
public ExecutionControl generate(ExecutionEnv ee, Map<String, String> map) throws Throwable {
return new DirectExecutionControl();
}
}, null)
.build();
shell.addToClasspath("Example.jar");
shell.eval("import com.example.test.C;");
shell.eval("System.out.println(C.C)"); //null
shell.eval("C.C = \"modified\";");
shell.eval("System.out.println(C.C)"); //"modified"
System.out.println(c.getDeclaredField("C").get(null)); //"initial"
}
}
如果 JVM 和 JShell实例
不共享任何内存,但是这是预期的输出,但是com.example.test.C
直接添加到项目中而不是动态加载它会如下更改结果:
shell.eval("import com.example.test.C;");
shell.eval("System.out.println(C.C)"); //"initial"
shell.eval("C.C = \"modified\";");
shell.eval("System.out.println(C.C)"); //"modified"
System.out.println(c.getDeclaredField("C").get(null)); //"modified"
为什么在运行时加载的类不共享 JVM 和 JShell实例 之间的内存?
编辑2:该问题似乎是由不同的类加载器引起的
在以上示例的上下文中执行以下代码:
System.out.println(c.getClassLoader()); //java.net.URLClassLoader
shell.eval("System.out.println(C.class.getClassLoader())"); //jdk.jshell.execution.DefaultLoaderDelegate$RemoteClassLoader
shell.eval("System.out.println(com.example.test.Main.class.getClassLoader())"); //jdk.internal.loader.ClassLoaders$AppClassLoader
这表明同一类com.example.test.C
由两个不同的类加载器加载。是否可以将类添加到JShell实例而无需再次加载它?如果否,为什么已经加载了静态加载的类?
解决方案是创建一个自定义LoaderDelegate
实现,该实现提供已加载类的实例,而不是再次加载它们。一个简单的示例是使用默认实现DefaultLoaderDelegate
(source)并覆盖findClass
其内部的方法RemoteClassLoader
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] b = classObjects.get(name);
if (b == null) {
Class<?> c = null;
try {
c = Class.forName(name);//Use a custom way to load the class
} catch(ClassNotFoundException e) {
}
if(c == null) {
return super.findClass(name);
}
return c;
}
return super.defineClass(name, b, 0, b.length, (CodeSource) null);
}
要创建一个有效的JShell实例,请使用以下代码
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");//Add custom classes to Classpath, otherwise they can not be referenced in the JShell
问题内容: 为了进行测试,我想从应用程序加载共享库的两个实例。库中的代码提供了API,但由于某些功能依赖于静态变量,因此它不允许我初始化库的两个(或多个)实例。 我目前正在为此lib编写单元测试,并且我想拥有两个实例,因为这将大大简化我的测试。 该库未链接到该程序。相反,我直接使用LoadLibrary / GetProcAddress(或linux上的dlopen / dlsym)加载它。为了区
问题内容: 我尝试将jar动态加载到Java项目中。 这是类加载器的代码: 以及Jar中包含的Class: } 它给了我: 您对此有什么想法吗?谢谢。 问题答案: 您的文件网址似乎无效。 “ Windows中的文件URI”说 对于本地Windows文件路径 Windows中相应的有效文件URI为: 这表明冒号后需要 三个斜杠 ,但是您要在其中计算的URL 在。之后仅有 两个斜线。也许 应该 或者你
主要内容:确定网站类型,影片详情信息,影片总数量,影片类型与类型码,编写完整程序本节讲解如何抓取豆瓣电影“分类排行榜”中的电影数据( https://movie.douban.com/chart),比如输入“犯罪”则会输出所有犯罪影片的电影名称、评分,效果如下所示: 确定网站类型 首先要明确豆瓣电影网站的类型,即是动态还是静态。检查方法:右键查看网页源码 —> 搜索“辛德勒的名单”关键字,如下图所示: 图1:分析网站类型 最终发现源码页中没有出现想要抓取的数据,只有一大堆的
本文向大家介绍angularjs实现柱状图动态加载的示例,包括了angularjs实现柱状图动态加载的示例的使用技巧和注意事项,需要的朋友参考一下 一 准备工作 1.引用文件 下面链接中有一个jquery.js文件,请在index.html中引用。 2.新建文件 新建一个js文件,编写指令。这也是我第一次写指令,指令可扩展性强,还很方便,当项目中重复使用的一些效果时可以通过指令来减少冗余的代码。
本文向大家介绍django echarts饼图数据动态加载的实例,包括了django echarts饼图数据动态加载的实例的使用技巧和注意事项,需要的朋友参考一下 如下所示: 后台关键代码: 网页(js中)取值关键代码: 1.取值: 2.饼图赋值: 效果图: 以上这篇django echarts饼图数据动态加载的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。
javadoc for意味着流管道中的“行为操作”通常必须是无状态的。然而,它所展示的如何不编写管道的示例似乎都涉及并行流。 这在多大程度上适用于顺序流? 我的问题是:我紧张是对的,还是上面的代码值得信任? 假设中的表达式使用了某种共享状态。当使用顺序流时,我们能相信它会正常工作吗?