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

时间:2011-10-29 08:55:47

标签: scala classloader

我想从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时,我无法找到类定义 - 它在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)

1 个答案:

答案 0 :(得分:3)

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

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

请参阅我的答案:scala classloaders confusion