Class.forName(...) 与 Class.forName(...) Thread.currentThread.getContextClassLoader.loadClass(...) 行为

发布于 2024-12-12 09:57:56 字数 3297 浏览 0 评论 0原文

我想从 Scala REPL 动态加载由 Guava 库定义的 Class 对象。但是,根据检索 Class 定义的方式,我观察到不同的行为:

scala> :cp guava-10.0.1.jar
Added '/Users/xxx/guava-10.0.1.jar'.  Your new classpath is:
"/Users/rouvoy/Development/tools/axis/default/lib:/Users/xxx/guava-10.0.1.jar"

scala> Class.forName("com.google.common.base.Ascii")
res0: java.lang.Class[_] = class com.google.common.base.Ascii

Class.forName(...) 方法工作正常并设法检索 Class 对象,但我想了解为什么在使用 ContextClassLoader 时,我无法找到 Class 定义,而它在 Java 中工作得很好?

scala> Thread.currentThread.getContextClassLoader.loadClass("com.google.common.base.Ascii")
java.lang.ClassNotFoundException: com.google.common.base.Ascii
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at .<init>(<console>:8)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
at java.lang.Thread.run(Thread.java:680)

scala> Class.forName("com.google.common.base.Ascii",true,Thread.currentThread.getContextClassLoader)
java.lang.ClassNotFoundException: com.google.common.base.Ascii
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at .<init>(<console>:8)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
at java.lang.Thread.run(Thread.java:680)

I'd like to load dynamically a Class object defined by the Guava library from the Scala REPL. However, I observe different behaviors depending on the way I retrieve the Class definition:

scala> :cp guava-10.0.1.jar
Added '/Users/xxx/guava-10.0.1.jar'.  Your new classpath is:
"/Users/rouvoy/Development/tools/axis/default/lib:/Users/xxx/guava-10.0.1.jar"

scala> Class.forName("com.google.common.base.Ascii")
res0: java.lang.Class[_] = class com.google.common.base.Ascii

The Class.forName(...) method works fine and manages to retrieve the Class object, but I would like to understand why, when using the ContextClassLoader, I am not able to locate the Class definition—while it works perfectly in Java?

scala> Thread.currentThread.getContextClassLoader.loadClass("com.google.common.base.Ascii")
java.lang.ClassNotFoundException: com.google.common.base.Ascii
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at .<init>(<console>:8)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
at scala.tools.nsc.interpreter.IMain$Request$anonfun$14.apply(IMain.scala:920)
at scala.tools.nsc.interpreter.Line$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$anon$2.run(package.scala:25)
at java.lang.Thread.run(Thread.java:680)

scala> Class.forName("com.google.common.base.Ascii",true,Thread.currentThread.getContextClassLoader)
java.lang.ClassNotFoundException: com.google.common.base.Ascii
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at .<init>(<console>:8)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
at scala.tools.nsc.interpreter.IMain$Request$anonfun$14.apply(IMain.scala:920)
at scala.tools.nsc.interpreter.Line$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$anon$2.run(package.scala:25)
at java.lang.Thread.run(Thread.java:680)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

把回忆走一遍 2024-12-19 09:57:57

Scala 和 Java 之间的类加载略有不同。当您为 scala 可执行文件(脚本或 .bat)指定 -cp 时,它不会添加到基类路径中,而只会添加到 Scala 类加载器中。我怀疑当您指定 :cp 时,REPL 也是如此。

要真正向 java 类路径添加某些内容,请使用 scala 或 scalac 的 -toolcp 选项。

请参阅我的回答:scala 类加载器混乱

The classloading is subtly different between Scala and Java. When you specify -cp to the scala executable (script or .bat), it doesn't get added to the base classpath, it only gets added to the Scala Class Loader. I suspect the same is true for the REPL when you specify :cp.

To really add something to the java classpath, use the -toolcp option to scala or scalac.

See my answer to: scala classloaders confusion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文