I have a regression test where I'm trying to count the number of instantiations of arrays. Specifically, I'm interested in counting how many times new int[..]
is called. I have put together the following ByteBuddy advice-based instrumentation, which I believe should catch all constructors, but this is not working for arrays (of any kind):
public class InstanceCounter {
public static void load() {
ClassInjector.UsingUnsafe.ofBootLoader().injectRaw(Collections.singletonMap("foo.bar.BootstrapState", readBytes(InstanceCounter.class.getClassLoader().getResource("foo/bar/BootstrapState.class"))));
new AgentBuilder.Default()
.ignore(none())
.disableClassFormatChanges()
.with(RedefinitionStrategy.RETRANSFORMATION)
.with(InitializationStrategy.NoOp.INSTANCE)
.with(TypeStrategy.Default.REDEFINE)
.type(any())
.transform(new Transformer() {
@Override
public Builder<?> transform(final Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
return builder.visit(Advice.to(InstanceCounter.class).on(any()));
}})
.installOn(ByteBuddyAgent.install());
}
@Advice.OnMethodEnter
public static void enter(final @Advice.Origin Class<?> origin) {
if (!BootstrapState.trace || BootstrapState.lock)
return;
BootstrapState.lock = true;
System.out.println(">>> " + origin);
BootstrapState.lock = false;
}
}
public class InstanceCounterTest {
@Test
public void test() {
InstanceCounter.load();
System.out.println("Creating array...");
BootstrapState.trace = true;
final Object[] y = new Object[3];
BootstrapState.trace = false;
System.out.println("Printing array: " + y);
}
}
When I run this test, I get the following results:
Creating array...
Printing array: [Ljava.lang.Object;@7f5eae0f
If I change final Object[] y = new Object[3]
to new Object()
, then the output is:
Creating array...
>>> class java.lang.Object
Printing array: [Ljava.lang.Object;@68562ad5
I've made the advice instrumentation as open as possible (at least as open as I think I can make it), but this is still not instrumenting construction of array objects.
Is is even possible to instrument construction of array objects?
Update 2020-07-28
As per the context of the original question, the provided answers express that ByteBuddy does not have direct support for automatic instrumentation of
new int[]
. However, for those interested in an alternate solution, I was able to achieve this kind of instrumentation with Byteman.
As pointed out, you cannot change array classes as they are not represented in a class file. Instead, you'd need to intercept their creation which requires some byte code parsing.
Byte Buddy exposes ASM, which it uses itself to do this kind of work, but it is much more manual work than intercepting a constructor.