【问题标题】:Why Does Clojure Use the Context Classloader by Default?为什么 Clojure 默认使用上下文类加载器?
【发布时间】:2012-11-16 19:22:25
【问题描述】:

为什么use-context-classloader默认设置为true?

为什么 Clojure 不使用当前的类加载器?

【问题讨论】:

  • 现在正在阅读这篇文章:javaworld.com/javaqa/2003-06/01-qa-0606-load.html 这对我来说是一个有趣的话题,作者得出的结论是上下文类加载器不太可能被框架所覆盖更可预测。我会把这个问题的答案留给真正知道的人。

标签: clojure classloader contextclassloader


【解决方案1】:

您可以通过将clojure.lang.Compiler.LOADER 设置为类加载器来覆盖其行为 即。

final ClassLoader ccl= ClojurePlugin.class.getClassLoader();
clojure.lang.Var.pushThreadBindings(clojure.lang.RT.map( clojure.lang.Compiler.LOADER, ccl) );
try {
  ...
  clojure.lang.RT.loadResourceScript( cljFile );
  ...
}finally{
  clojure.lang.RT.popThreadBindings();
}

ClojurePlugin 是你的类。

但是当您第一次使用 RT 类时(即加载 RT 类时),它将使用上下文类加载器来加载即。 clojure/core,所以你可能想把上面的代码包装成:

ClassLoader previous = Thread.currentThread().getContextClassLoader();
final ClassLoader parentClassLoader = ClojurePlugin.class.getClassLoader();
Thread.currentThread().setContextClassLoader(parentClassLoader);
try {
  ...
  //above code here
  ...
} finally {
  Thread.currentThread().setContextClassLoader(previous);
}

否则您可能会收到一些错误消息,例如:

Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath:
        at clojure.lang.RT.load(RT.java:432)
        at clojure.lang.RT.load(RT.java:400)
        at clojure.lang.RT.doInit(RT.java:436)
        at clojure.lang.RT.<clinit>(RT.java:318)
        ... 16 more

否则,如果你这样做而不是前者,你会得到类似的东西:

21:10:59 [SEVERE] java.io.FileNotFoundException: Could not locate Clojure resource on classpath: cljminecraft/core.clj
21:10:59 [SEVERE]       at clojure.lang.RT.loadResourceScript(RT.java:366)
21:10:59 [SEVERE]       at clojure.lang.RT.loadResourceScript(RT.java:346)
21:10:59 [SEVERE]       at clojure.lang.RT.loadResourceScript(RT.java:338)
21:10:59 [SEVERE]       at cljminecraft.ClojurePlugin.loadClojureFile(ClojurePlugin.java:25)
21:10:59 [SEVERE]       at cljminecraft.ClojurePlugin.loadClojureNameSpace(ClojurePlugin.java:38)
21:10:59 [SEVERE]       at cljminecraft.ClojurePlugin.start(ClojurePlugin.java:53)
21:10:59 [SEVERE]       at cljminecraft.BasePlugin.onEnable(BasePlugin.java:235)
21:10:59 [SEVERE]       at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
21:10:59 [SEVERE]       at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:374)
21:10:59 [SEVERE]       at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
21:10:59 [SEVERE]       at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:270)
21:10:59 [SEVERE]       at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:252)
21:10:59 [SEVERE]       at net.minecraft.server.MinecraftServer.j(MinecraftServer.java:320)
21:10:59 [SEVERE]       at net.minecraft.server.MinecraftServer.e(MinecraftServer.java:299)
21:10:59 [SEVERE]       at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:258)
21:10:59 [SEVERE]       at net.minecraft.server.DedicatedServer.init(DedicatedServer.java:147)
21:10:59 [SEVERE]       at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:398)
21:10:59 [SEVERE]       at net.minecraft.server.ThreadServerApplication.run(SourceFile:856)

如果你都不做(但你仍然调用clojure.lang.RT.loadResourceScript( cljFile ); 之类的东西,那么你会得到第一个错误(显然)

【讨论】:

  • 我实际上使用了不同的 ccl(不是类中的那个): final clojure.lang.DynamicClassLoader ccl = (clojure.lang.DynamicClassLoader)AccessController.doPrivileged( new PrivilegedAction() { @Override public Object run() { return new clojure.lang.DynamicClassLoader( ClojurePlugin.class.getClassLoader()); } });我后来通过 ccl.addURL(jarURL); 将 jar 文件添加到其类路径中;
  • 有趣的解决方案。我最终修改了 Clojure 本身的源代码,将类加载器更改为当前类加载器而不是上下文类加载器:groups.google.com/forum/?fromgroups=#!topic/clojure/gRhD0HOwFGc
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多