访问类字节码?

3
我的目标是在运行时不需要特别知道类文件的位置就能够访问表示字节码的byte[]。
我已经尝试了两种解决方案,其中一种解决方案效果较好,但我想知道是否有其他方法可以实现这个目标(或者第二种解决方案哪里出了问题,导致无法工作)。
我的第一种(稍微)成功的解决方案是使用java.lang.instrumentation ClassFileTransformer类来访问类的byte[]。尽管这个方案有效,但我认为一定还有更简单的方法来实现这个目标。
我的第二种解决方案是使用-Xbootclasspath JVM参数替换java.lang.ClassLoader,并使其具有访问加载类的byte[]的能力。我添加了一个简单的System.out.println调试消息来确认ClassLoader的覆盖正在工作,但它没有起作用。我从这篇论文中得到了这个想法。我的类与链接的论文中重新制作的Integer类类似。我还使用了类似的目录设置,以便使用JVM参数,看起来像这样:
java -Xbootclasspath/p:.\out\production\boot\java\lang TestLoader

我的想法是,使用我提供链接中的方法,ClassLoader类是不能被覆盖的。

我很想知道为什么我的尝试覆盖ClassLoader没有成功,并且想听听还有什么其他方法可以访问类的byte[]。


1
我的目标是访问表示类字节码的byte[]。不,那只是实现尚未命名的目标的策略。你想通过这样做为最终用户提供什么功能(即目标)? - Andrew Thompson
目前这更像是一个教育性的问题,我并没有开发需要使用这种策略的产品。 - mburke13
2个回答

4

您可以使用getResourceAsStream()直接读取类字节吗?

InputStream is = String.class.getResourceAsStream("String.class");

编辑添加备选方案:

(摘自评论)

考虑到需要涉及的所有可能性,使用ClassFileTransformerinstrumentation API可能是可行的方法。我不知道“清洁”的要求是什么,但如果问题在于必须为JVM指定命令行参数,则可以尝试使用Attach API - 您可以附加到已经运行的Java进程中,推入您的ClassFileTransformer,并查看JVM中已加载的所有类以及加载此后加载的任何类。


这个方法可以行得通,但是我可能没有表明我在运行时并没有直接访问类文件的权限。 - mburke13
@Matt,你在问题中指定的两个解决方案都是在运行时访问类文件。你能否澄清一下你所说的“在运行时没有访问类文件”的含义(即动态生成的字节码、自定义类加载器、其他什么等)? - prunge
我想要能够访问加载到JVM中的任何类的byte[]表示。有些类(例如String.class)我会知道名称,但其他类则不知道。此外,类文件可能存在于本地计算机上,也可能通过连接加载或动态生成。很抱歉这是一个如此广泛的可能性范围,但正如我所解释的那样,我想知道是否有一种方法可以涵盖所有这些可能性。 - mburke13
1
@Matt 鉴于需要涵盖的所有可能性,ClassFileTransformer 和 instrumentation API 可能是可行的方法。我不知道“clean”的要求是什么,但如果问题是必须指定 JVM 的命令行参数,您可以尝试使用 Attach API - 您可以附加到已经运行的 Java 进程,推入您的 ClassFileTransformer,并查看 JVM 中已加载的所有类以及之后加载的任何类。 - prunge
那听起来确实是我正在寻找的,我一定会去看看。谢谢! - mburke13
@prunge,您可以将您的评论重新发布为答案,以便获得积分。 - alexsmail

0

我认为你只是把引导类路径搞错了。假设类加载器的类文件是:

.\out\production\boot\java\lang\ClassLoader.class

你应该使用:

java -Xbootclasspath/p:.\out\production\boot TestLoader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接