使用 JDK9 获取 java.io.Serializable 时出现 Javassist NotFoundException

Javassist NotFoundException when getting java.io.Serializable with JDK9

我有以下代码:

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

在JDK8环境下运行时,如果使用java.io.Serializable调用此方法有效,但在JDK9环境下运行时,会抛出NotFoundException

这里有什么我忽略的地方吗?

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

documentation of ClassPool 说:

If get() is called on this object, it searches various sources represented by ClassPath to find a class file and then it creates a CtClass object representing that class file.

这似乎与class路径的概念有关。查看 ClassPath and CtClass 支持该假设。

如果是这样,那么 Javassist 可能不适合研究 JDK 9 的全新 modules.

如果我的猜测是正确的,你应该无法从池中得到 any JDK class。这应该很容易验证。

Java9 的当前 EA 版本不再发生这种情况。Class 文件现在始终可定位,即使它们封装在模块中也是如此。

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

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

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

直到 Java 8,这个 class 文件是可以访问的,因为大多数 class 加载程序依赖于在加载它之前查找 class 文件,以便上面的调用返回URL 指向文件。自 Java 9 起,命名模块的资源只能通过新的 API 方法 findResource(String, String) 使用,其中第二个参数命名 class.

的模块

简短的回答是:Javassist 不再与 Java 9 和 its dependant projects will. This is a known issue 的 none 一起使用当前的 Java 9 实现,并且希望在发布前得到修复。