7

I am trying to track allocations of all objects in JVM.

In the several documents about allocation profilers it was mentioned that the easiest way to do so is this: add invokestatic Tracker.trackAllocation()V instruction to java/lang/Object.<init> (normally it consists of a single return instruction, we add invokestatic before it, so it is 2 instructions now).

(I know that this approach is slow and will not track array allocations, but I wanted to start with simplest solution. Also I don't pass reference to the allocated object to tracker, but this will be added later.)

Class file is instrumented with JVM TI agent in onClassLoaded hook.

However, after adding invokestatic instruction JVM crashes with segfault. Tracker object is added to bootstrap classloader, so it should be visible at any stage. I tried adding nop instead of invokestatic, and JVM works fine with the modified Object class. So the problem is specifically with the invocation of some static method.

I also tried to instrument application (not part of base) classes and it worked fine - tracker was called and no crashes happened. Also I tried redefining Object at 2 points: when it is initially loaded (first loaded class), or after vmInit event (when all base classes are loaded and restrictions on jni are lifted).

Is there anything I am missing about instrumenting java.lang.Object?

Code for the agent is here: https://gist.github.com/Korobochka/3bf2f906f6ab85b22dec (Error checking is stripped, code for changing classes is also not included, but it works well enough for other classes)

Korobochka
  • 137
  • 2
  • 5
  • @apangin I added the gist with agent code to the bottom of the question. This is the version where Object is changed after vmInit. – Korobochka May 07 '15 at 14:50
  • 1
    I think the problem is that the `Tracker` class is an object itself, which needs to be instantiated before an object is created, but that would require loading the class first...and so on. You need to break that cycle somehow. – biziclop May 07 '15 at 15:00
  • Ideally by only instrumenting the class after `Tracker` has loaded. – biziclop May 07 '15 at 15:04
  • @biziclop In the code attached Object is retransformed on vmInit, and since `Tracker` is added to bootstrap class loader it is already loaded (`ClassFileLoadHook` was already called for `Tracker` before `RetransformClasses` call). Or you are talking about some different initialization? ``? – Korobochka May 07 '15 at 15:15
  • Yes, it can't be that then. – biziclop May 07 '15 at 15:28
  • What is JClass.h? Can't compile without it. Please also share the crash dump. – apangin May 07 '15 at 16:05
  • @apangin It is classfile reader/writer which I wrote. Rather ugly at the moment (also leaks memory and does not support some attributes), but seems to work. I will post complete project with makefile later today when I will get to the computer. – Korobochka May 07 '15 at 17:02

1 Answers1

5

Looks like the problem is in calling System.out.println from LeakAgentInterface. First of all, System.out may not be initialized yet. Second, println may allocate objects itself.

apangin
  • 92,924
  • 10
  • 193
  • 247
  • 1
    And this includes the `String` that will be printed which is also an object; even compile-time constant `String`s have to be allocated at runtime when they are used the first time… – Holger May 07 '15 at 18:47
  • Just checked, this is indeed the case. Thank you very much! I wasted a good couple of hours on this and the mistake was very simple and stupid =( But I was looking for the bug in C++ code only. Silly me. – Korobochka May 07 '15 at 19:11