5

Today I was exploring classes of huge applications (like jboss server with apps) with javaagent and instrumentation on my openjdk 7. I called retransform on all classes every 10 seconds, so their bytecode got in my ClassFileTransformer implementation.

My implementation simply keeps track of how bytecode of classes changes over time. First of all, I was surprised, that order of fields and methods, method access modifiers, contents of constant pool and other such things vary from one check to the other. But, still, it is documented.

What is not documented - that some items may be created in class'es constant pool and injected into methods. For now I noticed that to happen with numeric values (Longs, Doubles, Floats and such).

This is how it looks in javap; before:

pool:
...
#17 Float NaNf
method:
#1 fload #17 //NaNf
...

After something changed class during runtime:

pool:
...
#17 Float NaNf
#18 Float NaNf
method:
#1 fload #18 //NaNf <- look, it loads #18 now

I double checked, that no other transformers or agents are attached.

Why can't JVM just leave my bytecode the same? Where can I read about such optimisations/transformations (or what else is it)? I read JVM sources, but these only confused me more.

I'm just trying to create some kind of realtime bytecode verificator - a security tool.

Oroboros102
  • 2,214
  • 1
  • 27
  • 41
  • 1
    There's nothing that says that the generated code must be deterministic, so long as the *effect* of the code is deterministic. No doubt many of the differences occur because things hash into different buckets each run. – Hot Licks Aug 19 '13 at 20:11
  • Sorry, I didn't understand about buckets. What buckets do you mean? Btw, that code is not generated. It is compiled, put in jars and stays the same all the time. – Oroboros102 Aug 19 '13 at 20:17
  • Do you have any transformers that are changing the bytecode? – Antimony Aug 19 '13 at 20:41
  • @Antimony No. My returns null, and no other attached. – Oroboros102 Aug 19 '13 at 20:53
  • The code in the .class files stored in the file system does not change unless you change it. But a transformer, by definition, changes the storage image of the class file. – Hot Licks Aug 19 '13 at 20:56
  • @HotLicks I'm sure that my transformer does not change bytecodes and no other transformers are attached. – Oroboros102 Aug 19 '13 at 21:12
  • This is probably due to internal optimizations in the VM then, – Antimony Aug 19 '13 at 21:30
  • I suspect there is some transformation going on that you don't know about. – Hot Licks Aug 19 '13 at 21:32
  • How have you verified that no other javaagents are present? Bear in mind that it is possible for code to attach an agent to the jvm it is running in. – henry Aug 20 '13 at 09:06
  • @henry yes, I disabled agent attachment with `-XX:+DisableAttachMechanism`. And my agent is the only one in `-javaagent:` arguments. – Oroboros102 Aug 20 '13 at 09:48
  • possible duplicate of [Is the creation of Java class files deterministic?](http://stackoverflow.com/questions/14984984/is-the-creation-of-java-class-files-deterministic) – Joachim Sauer Aug 21 '13 at 09:11
  • While this may not strictly be a duplicate of http://stackoverflow.com/questions/14984984/is-the-creation-of-java-class-files-deterministic, the topic has been *extensively* covered over there. – Joachim Sauer Aug 21 '13 at 09:12
  • @Joachim Sauer Unfortunately, they are discussing compilation differences, while I have them during runtime. Still, thank you, that was interesting to read. – Oroboros102 Aug 21 '13 at 09:18
  • @Oroboros102: oh, then I misunderstood your question, Sorry. – Joachim Sauer Aug 21 '13 at 09:52

1 Answers1

1

What is not documented - that some items may be created in class'es constant pool and injected into methods.

Well, the article you have linked yourself clearly says:

The constant pool may have more or fewer entries. Constant pool entries may be in a different order; however, constant pool indices in the bytecodes of methods will correspond.

So it actually is documented. The reason is that it is not useful to remember each classes’ bytecode exactly thus repeating all the constant pool entries which are the same over lots of classes. The JVMs typically have an internal format which differs from ordinary class files and generate a class file once needed, e.g. when calling a transformer.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Actually, I'm concerned about method body change, not class pool change. But, "JVMs ... generate a class file once needed" makes it more clear. Do you have any ideas about how to detect class change (as bytecode or just some data in JVM)? – Oroboros102 Aug 27 '13 at 08:36
  • The question is, what kind of changes do you expect (want to detect)? The only non-internal changes are through transformers and the JVM will call all transformers one after another. So when you remove your periodical trigger you can use the fact that your transformer has been called as an indication that a transformation has happened. – Holger Aug 27 '13 at 17:09
  • I expect malicious changes to method's bytecode from both outside and inside JVM. Now I see, that the problem is probably unsolvable. Certainly not with help of bytecode transformers. – Oroboros102 Aug 28 '13 at 08:29
  • The question still is what kind of manipulation do you expect? The only interface for such manipulation is the transformer interface or the debugging interfaces similar to a transformer. Native code having the privileges necessary to overwrite arbitrary data will fly under the radar anyway. They could simply manipulate your transformer as well. Code from the outside has to go through the management API to load agents into the JVM. This can be disabled or protected with authentication mechanisms to be safe. That’s better than trying to detect incidents afterwards. – Holger Aug 28 '13 at 09:01
  • Thanks for an answer. For now I decided to use combination of disabling remote attachement & transformer that detects any retransforming calls. – Oroboros102 Aug 28 '13 at 11:45