Java:在同一个JVM中从运行时获取类的字节码

相关: 有没有办法在运行时获取类的字节码?

我正在为Clojure增加耐久性,我终于到了准备添加function的地步。 在Clojure中,函数通过调用方法(以及其他方式)被字节编译为类。 通过这种方式,function是一流的。 为了使这些持久,我需要序列化和反序列化这些类。 如何在不访问.class文件的情况下获取类的字节码?

如果我弄错了,请纠正我,但使用代理需要生成一个单独的VM,代理连接到第一个VM。 我需要从同一个VM做到这一点。

使用Serializable来设置和获取Class对象是不够的。 在反序列化时,我需要加载该类,并且在后续VM实例上,可能存在类名冲突。 我需要修改字节码,以便在反序列化/类加载时将类重命名为唯一的。

您可以编写自己的ClassLoader并破解一个方案,该方案在加载类时记录字节码。

您需要覆盖findClass以自己查找类文件,将其加载到内存中,将数据保存到某处(以便稍后进行序列化),然后调用defineClass在JVM中定义该类。

除非您通过棘手的类加载器运行代码,否则您应该可以执行以下操作:

 Class clazz = .... String className = clazz.getCanonicalName(); // eg "foo.Bar" String resourceName = ... // map className to a resource name; eg "/foo/Bar.class" InputStream is = clazz.getClassLoader.getResourceAsStream(resourceName); 

这使您可以处理“.class”文件的内容…如果可以找到它。

注意事项。 一些类加载器可能会:

  • 不要让我们打开“.class”资源,
  • 给你一个加密的字节码流,或
  • 由于类加载器执行了一些即时转换,因此可以为字节码提供正确运行的字节码。

如果这种方法不起作用,那么你几乎没有选择,因为JVM没有提供访问加载的实际字节码的方法。

您也可以使用Java Instrumentation API。 在调用defineClass之前,您可以访问类文件的字节。 你也可以改变它们!