12

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

我正在为 Clojure 添加持久性,我终于可以准备添加功能了。在 Clojure 中,函数被字节编译成带有调用方法(以及其他方法)的类。这样,功能是一流的。为了使这些持久化,我需要对这些类进行序列化和反序列化。如何在无法访问 .class 文件的情况下获取类的字节码?

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

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

4

3 回答 3

5

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

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

于 2010-11-09T06:39:35.530 回答
3

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

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

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

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

  • 根本不允许打开“.class”资源,
  • 给你一个加密的字节码流,或者
  • 由于类加载器执行的一些即时转换,给你的字节码也不完全是正在运行的字节码。

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

于 2010-11-09T06:30:57.980 回答
1

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

于 2012-07-20T19:23:29.433 回答