java.lang.ClassFormatError: StackMapTable format error: bad offset for Uninitialized in method Test.run()V
See original GitHub issueClassFormatError happens when advice is applied to a method that
- has a leading stack frame
- creates a new value with the first instruction
- leaves the newly create value uninitialized and performs a jump
Seems like bytebuddy inserts an extra
nop
before original method code and the uninitialized value in stack frame points to thatnop
instead of the followingnew
instruction.
import static net.bytebuddy.matcher.ElementMatchers.named;
import java.lang.invoke.MethodHandles;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.ClassWriter;
import net.bytebuddy.jar.asm.Label;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;
public class Main implements Opcodes {
public static void main(String... args) throws Exception {
new AgentBuilder.Default().type(named("Test"))
.transform(new AgentBuilder.Transformer.ForAdvice().advice(named("run"), RunnableAdvice.class.getName()))
.asTerminalTransformation()
.installOn(ByteBuddyAgent.install());
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = cw;
cv.visit(
V9,
ACC_PUBLIC | ACC_SUPER,
"Test",
null,
"java/lang/Object",
new String[] { "java/lang/Runnable" });
{
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
{
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
mv.visitCode();
Label newInsn = new Label();
//XXX ClassFormatError does not happen without this line
mv.visitFrame(F_SAME, 0, null, 0, null);
mv.visitTypeInsn(NEW, "java/util/ArrayList");
Label jump = new Label();
mv.visitJumpInsn(GOTO, jump);
mv.visitFrame(F_FULL, 0, null, 1, new Object[] { "java/lang/Throwable" });
mv.visitInsn(NOP);
mv.visitInsn(NOP);
mv.visitInsn(NOP);
mv.visitInsn(ATHROW);
mv.visitLabel(jump);
mv.visitFrame(F_FULL, 0, null, 1, new Object[] { newInsn });
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
mv.visitVarInsn(ASTORE, 1);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
cv.visitEnd();
byte[] bytes = cw.toByteArray();
Class<?> c = MethodHandles.lookup().defineClass(bytes);
Runnable r = (Runnable) c.getDeclaredConstructor().newInstance();
r.run();
}
public static class RunnableAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void enter() {
System.err.println("enter");
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void exit() {
System.err.println("exit");
}
}
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:9 (7 by maintainers)
Top Results From Across the Web
ASM & Javaagent bytecode instrumentation ... - Stack Overflow
java.lang.ClassFormatError: StackMapTable format error: bad offset for Uninitialized in method org.apache.commons.math.ode.
Read more >Hello World Plugin - ClassFormatError : StackMapTable ...
When I run the plugin I get the below error. Exception in thread "main" java.lang.ClassFormatError: StackMapTable format error: bad class ...
Read more >ClassFormatError: StackMapTable format error: bad offset for ...
Coding example for the question ASM & Javaagent bytecode instrumentation: ClassFormatError: StackMapTable format error: bad offset for Uninitialized-Java.
Read more >[jboss-jira] [JBoss JIRA] (JASSIST-161) java.lang ...
ClassFormatError : StackMapTable format error: bad offset for Uninitialized in method Process._removeFiles_(LProcessFile;)V The intent of the ...
Read more >java.lang.VerifyError running Daikon with Apache Hadoop
Exception in thread "main" java.lang.ClassFormatError: StackMapTable format error: bad offset for Uninitialized in method org.apache.hadoop.fs.FileSystem.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
My bad, I put the test in a package that Byte Buddy ignores by default.
Fixed on master.