5

for bytecode instrumentation in java, there is the asm framework and the bcel and javaassist libraries.

However I need to do instrumentation in native code, since some java classes are already loaded by the time the javaagent runs, eg java.lang.Thread, java.lang.Class, etc

is there any library for instrumenting java classes in native code?

Edit: Seems there is a bit of confusion.

What I want is: Create a native java agent, which uses JVMTI apis to change the bytecode of a class while its being loaded, using the OnClassLoad event hook.

pdeva
  • 43,605
  • 46
  • 133
  • 171
  • 5
    What is the original problem you need to solve? – Thorbjørn Ravn Andersen Jan 22 '12 at 11:58
  • What do you mean by "native code"? http://www.cs.ioc.ee/~ando/jbe/ provides a tool enable you to edit java bytecode directly – Gelin Luo Jan 22 '12 at 13:35
  • @ThorbjørnRavnAndersen I want to instrument classes like Thread and Class, which are loaded before a JavaAgent loads, thus they have to be instrumented in a native agent. – pdeva Jan 22 '12 at 18:45
  • cant really accept an answer when there isnt one, like in this thread... – pdeva Jan 22 '12 at 20:17
  • I was wondering how did you solve this issue after all? I'm about to evaluate an option of using a native agent that can instrument bytecode for certain classes and still cannot find any library in C/C++ that makes it possible – Mark Bramnik Nov 08 '22 at 06:08

3 Answers3

9

I encountered this problem during my doctoral research. The answer that worked best for me was to perform the byte-code modification in a separate JVM using a java library (I used ASM).

I used the JVMTI class load hook to capture the class file and transmit it to the separate JVM using a tcp connection. Once the class had been modified within the separate JVM I returned it to the JVMTI Agent, which copies it into VM memory and returns a pointer to the modified class file to the JVM.

I found that it was too difficult to weave classes within the same JVM as was being profiled as the system class files I wanted to modify (java.lang.Object, for example) had to be loaded before any class files I needed to perform weaving. I hunted for c/c++ bytecode libraries without much success, before settling on the separate JVM approach I finally used.

You can parameterize the JVMTI agent with the hostname/port of the weaver JVM, or you could use some form of discovery, depending on your requirements.

Stephen Nelson
  • 939
  • 1
  • 7
  • 22
  • 3
    Several other answers are mildly incorrect or flat-out wrong. You can change the bytecode of a class which has been loaded - even system classes. Once a class has been loaded you may not affect its external signature (add fields/methods) but you may change method bodies. The basic heapTracker JVMTI distributed with the JVM demonstrates changing the behaviour of java.lang.Object.(). – Stephen Nelson Apr 20 '12 at 14:44
3

The JIT will turn byte code into native code. If you want to produce native code, you need to let the JIT do it or write native code which is called via JNI.

Perhaps what you are trying to achieve can be done simpler another way.

Create a native java agent, which uses JVMTI apis to change the bytecode of a class while its being loaded, using the OnClassLoad event hook.

Though you don't need to do what you want. Why make the solution more complicated (and less likely to work) than it needs to be?

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I dont want to produce native code. I want to change the 'bytecode' of a class while its being loaded in a native agent using a OnClassLoad hook – pdeva Jan 22 '12 at 18:07
  • In that case, your question doesn't make any sense. Why would you want need to use native code to produce byte code? – Peter Lawrey Jan 22 '12 at 18:11
  • "Some java classes are already loaded by the time the javaagent runs", eg Thread, Hashmap, etc. – pdeva Jan 22 '12 at 18:39
  • Each ClassLoader can load these classes and re-load the byte code (with limitations) The system starts with a BootStrap class loader, the application itself starts in itself own class loader. – Peter Lawrey Jan 22 '12 at 18:58
  • 1
    http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html#redefineClasses%28java.lang.instrument.ClassDefinition...%29 – Peter Lawrey Jan 22 '12 at 19:02
  • If you want to modify system classes, the simplest thing to do is change a copy (from src.zip), compile it and add it to the boot class path (or add it to the endorsed directory) – Peter Lawrey Jan 22 '12 at 19:14
  • 1
    i know about redefine classes but it doesnt allow adding fields. also recompiling rt.jar is not an option. you clearly have no idea about any native bytecode instrumentation library. please stop suggesting alternatives that wont work and keep to the original question. – pdeva Jan 22 '12 at 20:17
  • You are right, I have used byte inject from native code because I have always been able to find another way to do this. I have never tried to recompile the `rt.jar` just the classes I wanted to alter. If you want to write a profiler which changes the bytecode of every classes, you right that you need a native library to do this. However, I have always used an existing one i.e. YourKit to do this rather than write it myself. – Peter Lawrey Jan 22 '12 at 20:23
  • what made you assume i want to build a profiler. again silly advice about something i dont care about. – pdeva Jan 22 '12 at 20:26
  • Because you appear to be unwilling or unable to say why you really need to use native agent, you just leave to others to guess. You don't appear to care that people are trying to help you even though you are not willing to listen. – Peter Lawrey Jan 22 '12 at 20:29
  • I think i made it pretty darn clear. I want to instrument classes like Thread, Class, etc. Now if you know a native bytecode instrumentor tell me about it, or leave this thread alone. I dont care to explain my eventual product since i dont think its relevant. – pdeva Jan 22 '12 at 20:33
-2

You cannot change the byte code of a class once it has been loaded. You can either make sure your instrumentation runs before it is loaded, or you can create a new ClassLoader, and re-load the classes inside of it by not asking the parent class. You can't use those classes with code loaded outside of the ClassLoader though, as that code will refer to the earlier loaded, non-altered class.

Martin Probst
  • 9,497
  • 6
  • 31
  • 33
  • 1
    I dont want to change the bytecode once its been loaded. I want to use a native agent to change the bytecode *while* the class is being loaded – pdeva Jan 22 '12 at 18:07