7

我有以下代码:

private static CtClass resolveCtClass(String clazz) throws NotFoundException {
  ClassPool pool = ClassPool.getDefault();
  return pool.get( clazz );
}

在JDK8下运行时,如果使用调用这个方法java.io.Serializable,它可以工作,但是在JDK9环境下运行时,它会抛出NotFoundException.

我在这里忽略了什么吗?

4

2 回答 2

7

Java 9 的当前 EA 版本不再发生这种情况。类文件现在总是可定位的,即使它们被封装在一个模块中。

这是 Java 9 模块封装的结果,其中非导出资源不再通过ClassLoaderAPI 可用。在幕后,Javassist 调用

ClassLoader.getSystemClassLoader().findResource("java/io/Serializable.class");

获取Serializable. 然后它解析这个类文件并以类似于 Java 反射 API 的方式表示信息,但不加载类,以便在加载之前可以对其进行编辑。

在 Java 8 之前,这个类文件是可访问的,因为大多数类加载器依赖于在加载类文件之前查找类文件,以便上述调用返回URL指向该文件的指针。从 Java 9 开始,命名模块的资源只能通过新的 API 方法获得findResource(String, String),其中第二个参数命名该类的模块。

简短的回答是:Javassist 不再适用于 Java 9,并且它的任何依赖项目都不会。这是当前 Java 9 实现的一个已知问题,有望在发布之前得到修复。

于 2016-06-19T08:52:52.913 回答
1

(我从未使用过 Javassist,所以我只是在黑暗中拍摄,在这里......)

文档ClassPool说:

如果get()在这个对象上调用,它会搜索由 表示的各种源ClassPath以找到一个类文件,然后它创建一个CtClass表示该类文件的对象。

这似乎与类路径的概念有关。查看ClassPathCtClass支持该假设。

如果是这种情况,那么 Javassist 可能不适合研究 JDK 9 的全新模块

如果我的猜测是正确的,您应该无法从池中获取任何JDK 类。这应该很容易验证。

于 2016-06-18T07:28:04.643 回答