通过java.lang.Object检测数组

通过java.lang.Object检测数组,java,instrumentation,Java,Instrumentation,我目前正在一个通过ASM库大量使用动态字节码修改例程的平台上工作。除了array类之外,我已经能够成功地为所有必需的系统类插入仪器。(例如String[],int[]等)这是因为数组类本身是一种动态类型,因此就我所知,rt.jar中实际上没有类文件可供插入 然而,我确实想到,即使是数组类型也扩展了java.lang.Object,因此尽管修改对象类并不理想,尤其是因为它会导致任何更改传播到所有子类,但它可能允许我间接地向数组类添加一个额外的基元字段,顺便说一句,这就是我想要实现的一切 除了我提到

我目前正在一个通过ASM库大量使用动态字节码修改例程的平台上工作。除了array类之外,我已经能够成功地为所有必需的系统类插入仪器。(例如String[],int[]等)这是因为数组类本身是一种动态类型,因此就我所知,rt.jar中实际上没有类文件可供插入

然而,我确实想到,即使是数组类型也扩展了java.lang.Object,因此尽管修改对象类并不理想,尤其是因为它会导致任何更改传播到所有子类,但它可能允许我间接地向数组类添加一个额外的基元字段,顺便说一句,这就是我想要实现的一切


除了我提到的明显警告之外,这是否会导致任何其他与平台相关的问题

您可能难以获取和设置字段

JVM规范中对和指令的描述(如果我理解正确的话)表明它们不用于阵列。要引用,对于
getfield

objectref的类型不能是数组类型

putfield

objectref的类不能是数组


但是,“如果指令描述中的某些约束(必须或不必须)在运行时未得到满足,则Java虚拟机的行为是未定义的”,因此它可能会正常工作。

不插入对象,最简单的方法是用您选择的编译版本替换它。假设这是可行的,您可以使用仪器使其更便于携带


注意:我发现JVM不喜欢对象有额外的方法(如果您添加了多个方法,就会出现奇怪的错误)

这应该不是问题,因为我可以将公共字段注入对象,然后直接访问它。我认为这仍然是未定义的行为,因为对象的动态类型是数组类型。我认为您可能是对的。在任何情况下,似乎有许多基于C++的JVM模块需要更新,以便使其能够正确地运行,因为在一些地方隐式地使用JVM平台硬编码的对象偏移。我对答案投了赞成票,因为提供的JVM规范信息很有用。@GilesThompson,如果您只是想跟踪一些数组实例的元数据,在
WeakHashMap
中使用它们作为键可能就足够了。这正是我在本例中必须采用的方法。是的,从某种意义上说,这就是我对所有系统类所做的,因为在我的应用程序之前加载它们时,不可能动态地转换它们,并且插装框架不允许您这样做加载类后更改其结构的步骤。在过去,您是否成功地将一个或多个字段添加到一个对象而没有出现任何问题?我没有尝试添加字段,但如果它能够工作,您可以将其添加到源代码的副本中,并将其放在预先设置的引导类路径上。即使它在一个虚拟机上工作,我怀疑它不会在所有虚拟机上工作。顺便说一句,要通过Object向数组添加代码,您不需要添加字段。正如我在原始帖子中所述,我只是尝试向Object类添加一个字段,就像添加代码一样。不幸的是,这似乎比它的价值更麻烦,因为根据这里的信息:JVM的部分依赖于硬编码的对象偏移量添加字段意味着重新计算这些偏移量,并将它们放置在相应的C++文件中所需的所有值中。如果添加字段,则将添加到每个子类。添加方法的影响较小。正如您所说,不同的JVM会有不同的限制。您是正确的,就像我在OP中所说,向对象添加字段并不理想,但我需要能够向array类添加字段&我想不出任何其他方法。我正在使用的平台为每个对象分配一个Id,该Id存储在这个额外的字段中。然而,数组是一个特例,因为我无法直接访问数组类字节码。目前,我只是使用映射将ID与数组对象相关联,但我想我更愿意将此信息直接存储到数组实例中。现在看来,如果没有大量的额外工作,这将是不可能的。