Why doesn't the Java byte fade on this byte?

I am working on code that computes entries in a StackFrameMap (SFM). The goal is to be able to generate records (SFMs) that make the Java 7 bytecode verifier happy. Following the TDD methodology, I started by creating dummy SMF entries for the verifier to complain; I would replace them with my correctly calculated entries to see that I am doing this correctly.

The problem is this: I can't get the bytecode verifier to complain. Here is an example starting with Java source code (this code should not do anything useful):

public int stackFrameTest(int x) { if (x > 0) { System.out.println("positive x"); } return -x; } 

This generates the following bytecode (with SFM):

  public int stackFrameTest(int); flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: iload_1 1: ifle 12 4: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream; 7: ldc #85 // String positive x 9: invokevirtual #55 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 12: iload_1 13: ineg 14: ireturn StackMapTable: number_of_entries = 1 frame_type = 12 /* same */ 

Now I am modifying SFM to contain this:

  StackMapTable: number_of_entries = 1 frame_type = 255 /* full_frame */ offset_delta = 12 locals = [ double, float ] stack = [ double ] 

As you can see, this is completely fictitious, but it loads without errors. I read the JVM specification and I could not understand why this would work. I do not use the SplitBytecodeVerifier parameter.

EDIT . According to the accepted answer below, Eclipse was configured to release Java 6 class files (version 50.0). Classfiles of this version will quietly ignore issues with StackFrameMap. After changing the setting to use the standard Java 7 style file (51.0), it worked as expected.

+8
java bytecode bytecode-manipulation
source share
1 answer

I can not reproduce your results. I tried changing the stack frame and it could not load as expected. If you want, I can post the modified class file.

It is not clear what happened, but you almost certainly made a mistake. The most likely explanation is that your cool file is version 50.0, in which case the JVM will revert to a normal check if the stack table is invalid. You need to set the version to 51.0 in order to force a template check. Another possibility is that you simply messed up the file editing and didn’t actually save the changes or make the changes you thought you made.

Here is the assembly for my modified class file.

 .version 51 0 .class super public StackFrameTest4 .super java/lang/Object .method public <init> : ()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object <init> ()V return .end method .method static public main : ([Ljava/lang/String;)V .limit stack 2 .limit locals 1 new StackFrameTest dup invokespecial StackFrameTest <init> ()V bipush 42 invokevirtual StackFrameTest stackFrameTest (I)I pop return .end method .method public stackFrameTest : (I)I .limit stack 2 .limit locals 2 iload_1 ifle L12 getstatic java/lang/System out Ljava/io/PrintStream; ldc 'positive x' invokevirtual java/io/PrintStream println (Ljava/lang/String;)V L12: .stack full locals Double Float stack Double .end stack iload_1 ineg ireturn .end method 
+5
source share

All Articles