4

ClassNotFound(是的,我知道,有很多关于这个异常的帖子;我在这里和其他地方搜索过,找不到解释)

为什么 Class.forName 失败?

groovy> class Foo { 
groovy> } 
groovy> def f = new Foo() 
groovy> def cname = f.getClass().getName() 
groovy> def p = f.getClass().getPackage() 
groovy> def l = f.getClass().getClassLoader() 
groovy> println "Foo class name: $cname" 
groovy> println "Foo package: $p" 
groovy> println "Foo class loader: ${f.getClass().getClassLoader().toString()}" 
groovy> println "Current class loader: ${this.getClass().getClassLoader().toString()}" 
groovy> try { 
groovy>     Class.forName(cname) 
groovy> } catch (Exception e) { 
groovy>     println e 
groovy> } 
groovy> l.findClass("Foo") 



Foo class name: Foo
Foo package: null
Foo class loader: groovy.lang.GroovyClassLoader$InnerLoader@2d275595
Current class loader: groovy.lang.GroovyClassLoader$InnerLoader@2d275595
java.lang.ClassNotFoundException: Foo
Exception thrown
Oct 16, 2012 4:43:28 PM org.codehaus.groovy.runtime.StackTraceUtils sanitize
WARNING: Sanitizing stacktrace:
java.lang.ClassNotFoundException: Foo

谢谢!

4

2 回答 2

3

给出的答案基本上是正确的,但它缺少一个重要的信息位。Class.forName(String)是从 Java 调用 Java 的 Java 方法。它需要让类加载器加载给定的类。它通过使用内部方法遍历调用堆栈来获取加载程序。虽然对于 java 来说,上升一级是正常做的正确的事情,但在 Groovy 中是不正确的。Groovy 中的每个方法调用都可以包含来自生成方法、invokedynamic 和反射的可变数量的中间调用堆栈元素。但通常父调用堆栈帧不包含真正的调用者类。相反,您最终会进入 groovy 运行时的加载器,甚至是 java 运行时的加载器。您的 shell 中的类是这些类的子类,因此加载程序不可能找到请求的类。

于 2013-08-23T08:10:34.573 回答
2

这是由于 ClassLoader。shell 内部的ClassLoader(即你在shell 中定义的类)不同于运行shell 的ClassLoader(你需要运行shell 的jar)。这就是该命令Class.forName("Foo", true, this.class.classLoader)有效的原因,因为您在 shell 中指定了 ClassLoader

尝试

def shell=new GroovyShell()

def f=shell.evaluate("class Foo{Foo(){println this.class.classLoader}};def f=new Foo()")

println shell.class.classLoader
shell.evaluate("println this.class.classLoader")

println "-----------"
println Class.forName("Foo", true, f.class.classLoader)
println Class.forName("Foo", true, this.class.classLoader)

您将看到第一个 Class.forName 有效,而不是第二个。运行脚本类似,因为它会创建一个不共享 shell 的 ClassLoader 的脚本类

执行 Class.forName 不会在脚本上下文中使用与 this 相同的 this。

不确定它是否足够清楚:(

于 2012-10-18T07:12:50.210 回答