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

时间:2016-06-18 00:54:34

标签: javassist java-9

我有以下代码:

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

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

这里有什么我忽略的吗?

2 个答案:

答案 0 :(得分:7)

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

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

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

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

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

简短的回答是:Javassist不再使用Java 9,its dependant projects也不会。这是具有当前Java 9实现的known issue,并且有望在发布之前得到修复。

答案 1 :(得分:1)

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

documentation of ClassPool说:

  

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

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

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

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