/*
* Copyright (c) 2013-2017 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.test;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_BYTECODE_STATIC_INITIALISER_SIGNATURE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE;
import static org.junit.Assert.*;
import java.io.File;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.adoptopenjdk.jitwatch.loader.BytecodeLoader;
import org.adoptopenjdk.jitwatch.model.IMetaMember;
import org.adoptopenjdk.jitwatch.model.JITDataModel;
import org.adoptopenjdk.jitwatch.model.MemberSignatureParts;
import org.adoptopenjdk.jitwatch.model.MetaClass;
import org.adoptopenjdk.jitwatch.model.bytecode.BCParamConstant;
import org.adoptopenjdk.jitwatch.model.bytecode.BCParamNumeric;
import org.adoptopenjdk.jitwatch.model.bytecode.BCParamString;
import org.adoptopenjdk.jitwatch.model.bytecode.BCParamSwitch;
import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction;
import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC;
import org.adoptopenjdk.jitwatch.model.bytecode.ExceptionTable;
import org.adoptopenjdk.jitwatch.model.bytecode.ExceptionTableEntry;
import org.adoptopenjdk.jitwatch.model.bytecode.IBytecodeParam;
import org.adoptopenjdk.jitwatch.model.bytecode.LineTable;
import org.adoptopenjdk.jitwatch.model.bytecode.LineTableEntry;
import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode;
import org.adoptopenjdk.jitwatch.model.bytecode.Opcode;
import org.junit.Test;
public class TestBytecodeLoader
{
@Test
public void testBytecodeSignature()
{
String fqClassName = "java.lang.StringBuilder";
String methodName = "charAt";
Class<?>[] params = new Class<?>[] { int.class };
IMetaMember member = UnitTestUtil.createTestMetaMember(fqClassName, methodName, params, char.class);
ClassBC classBytecode = BytecodeLoader.fetchBytecodeForClass(new ArrayList<String>(), fqClassName, false);
MemberBytecode memberBytecode = classBytecode.getMemberBytecode(member);
assertNotNull(memberBytecode);
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();
assertNotNull(instructions);
}
@Test
public void testParseBytecodes()
{
StringBuilder builder = new StringBuilder();
builder.append("0: ldc #224 // int 1000000").append(S_NEWLINE);
builder.append("2: istore_1").append(S_NEWLINE);
builder.append("3: aload_0").append(S_NEWLINE);
builder.append("4: arraylength").append(S_NEWLINE);
builder.append("5: iconst_1").append(S_NEWLINE);
builder.append("6: if_icmpne 28").append(S_NEWLINE);
builder.append("9: aload_0").append(S_NEWLINE);
builder.append("10: iconst_0").append(S_NEWLINE);
builder.append("11: aaload").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(9, instructions.size());
BytecodeInstruction i0 = instructions.get(0);
assertEquals(0, i0.getOffset());
assertEquals(Opcode.LDC, i0.getOpcode());
assertEquals(true, i0.hasParameters());
assertEquals(1, i0.getParameters().size());
IBytecodeParam paramI0 = i0.getParameters().get(0);
assertTrue(paramI0 instanceof BCParamConstant);
assertEquals(224, paramI0.getValue());
assertEquals(true, i0.hasComment());
assertEquals("// int 1000000", i0.getComment());
BytecodeInstruction i1 = instructions.get(1);
assertEquals(2, i1.getOffset());
assertEquals(Opcode.ISTORE_1, i1.getOpcode());
assertEquals(false, i1.hasParameters());
assertEquals(0, i1.getParameters().size());
assertEquals(false, i1.hasComment());
assertEquals(null, i1.getComment());
BytecodeInstruction i5 = instructions.get(5);
assertEquals(6, i5.getOffset());
assertEquals(Opcode.IF_ICMPNE, i5.getOpcode());
assertEquals(1, i5.getParameters().size());
assertEquals(true, i5.hasParameters());
IBytecodeParam paramI5 = i5.getParameters().get(0);
assertTrue(paramI5 instanceof BCParamNumeric);
assertEquals(28, paramI5.getValue());
assertEquals(false, i5.hasComment());
assertEquals(null, i5.getComment());
}
@Test
public void testParseBytecodeRegressionIinc()
{
StringBuilder builder = new StringBuilder();
builder.append("0: lconst_0").append(S_NEWLINE);
builder.append("1: lstore_2").append(S_NEWLINE);
builder.append("2: iconst_0").append(S_NEWLINE);
builder.append("3: lstore 2").append(S_NEWLINE);
builder.append("4: iinc 4, 1").append(S_NEWLINE);
builder.append("7: goto 47").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(6, instructions.size());
BytecodeInstruction i4 = instructions.get(4);
assertEquals(4, i4.getOffset());
assertEquals(Opcode.IINC, i4.getOpcode());
assertEquals(true, i4.hasParameters());
assertEquals(2, i4.getParameters().size());
IBytecodeParam paramI4a = i4.getParameters().get(0);
IBytecodeParam paramI4b = i4.getParameters().get(1);
assertTrue(paramI4a instanceof BCParamNumeric);
assertTrue(paramI4b instanceof BCParamNumeric);
assertEquals(4, paramI4a.getValue());
assertEquals(1, paramI4b.getValue());
assertEquals(false, i4.hasComment());
}
@Test
public void testIloadW()
{
StringBuilder builder = new StringBuilder();
builder.append("1: iload_w 340").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(1, instructions.size());
BytecodeInstruction i = instructions.get(0);
assertEquals(1, i.getOffset());
assertEquals(Opcode.ILOAD, i.getOpcode());
assertEquals(true, i.hasParameters());
assertEquals(1, i.getParameters().size());
BCParamNumeric varIndex = (BCParamNumeric) i.getParameters().get(0);
assertEquals(Integer.valueOf(340), varIndex.getValue());
}
@Test
public void testParseBytecodeRegressionNegativeInc()
{
StringBuilder builder = new StringBuilder();
builder.append("0: lconst_0").append(S_NEWLINE);
builder.append("1: lstore_2").append(S_NEWLINE);
builder.append("2: iconst_0").append(S_NEWLINE);
builder.append("3: lstore 2").append(S_NEWLINE);
builder.append("4: iinc 4, -1").append(S_NEWLINE);
builder.append("7: goto 47").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(6, instructions.size());
BytecodeInstruction i4 = instructions.get(4);
assertEquals(4, i4.getOffset());
assertEquals(Opcode.IINC, i4.getOpcode());
assertEquals(true, i4.hasParameters());
assertEquals(2, i4.getParameters().size());
IBytecodeParam paramI4a = i4.getParameters().get(0);
IBytecodeParam paramI4b = i4.getParameters().get(1);
assertTrue(paramI4a instanceof BCParamNumeric);
assertTrue(paramI4b instanceof BCParamNumeric);
assertEquals(4, paramI4a.getValue());
assertEquals(-1, paramI4b.getValue());
assertEquals(false, i4.hasComment());
}
@Test
public void testParseBytecodeRegressionNewArray()
{
StringBuilder builder = new StringBuilder();
builder.append("3: newarray int").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(1, instructions.size());
BytecodeInstruction i0 = instructions.get(0);
assertEquals(3, i0.getOffset());
assertEquals(Opcode.NEWARRAY, i0.getOpcode());
assertEquals(true, i0.hasParameters());
assertEquals(1, i0.getParameters().size());
IBytecodeParam paramI0 = i0.getParameters().get(0);
assertTrue(paramI0 instanceof BCParamString);
assertEquals("int", paramI0.getValue());
assertEquals(false, i0.hasComment());
}
@Test
public void testParseBytecodeRegressionTableSwitch()
{
StringBuilder builder = new StringBuilder();
builder.append("0: lconst_0").append(S_NEWLINE);
builder.append("1: lstore_2").append(S_NEWLINE);
builder.append("2: iconst_0").append(S_NEWLINE);
builder.append("3: tableswitch { // -1 to 5").append(S_NEWLINE);
builder.append(" -1: 100").append(S_NEWLINE);
builder.append(" 0: 101").append(S_NEWLINE);
builder.append(" 1: 102").append(S_NEWLINE);
builder.append(" 2: 103").append(S_NEWLINE);
builder.append(" 3: 104").append(S_NEWLINE);
builder.append(" 4: 105").append(S_NEWLINE);
builder.append(" 5: 106").append(S_NEWLINE);
builder.append(" default: 107").append(S_NEWLINE);
builder.append("}").append(S_NEWLINE);
builder.append("99: lstore_2").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(5, instructions.size());
BytecodeInstruction i3 = instructions.get(3);
assertEquals(3, i3.getOffset());
assertEquals(Opcode.TABLESWITCH, i3.getOpcode());
assertEquals(true, i3.hasParameters());
assertEquals(1, i3.getParameters().size());
IBytecodeParam paramI0 = i3.getParameters().get(0);
assertTrue(paramI0 instanceof BCParamSwitch);
BytecodeInstruction i99 = instructions.get(4);
assertEquals(99, i99.getOffset());
assertEquals(Opcode.LSTORE_2, i99.getOpcode());
assertEquals(false, i99.hasParameters());
}
@Test
public void testParseBytecodeRegressionTableSwitch2()
{
StringBuilder builder = new StringBuilder();
builder.append("39: ldc #8 // int 1000000").append(S_NEWLINE);
builder.append("41: if_icmpge 104").append(S_NEWLINE);
builder.append("44: iload 5").append(S_NEWLINE);
builder.append("46: iconst_3").append(S_NEWLINE);
builder.append("47: irem ").append(S_NEWLINE);
builder.append("48: tableswitch { // 0 to 2").append(S_NEWLINE);
builder.append(" 0: 76").append(S_NEWLINE);
builder.append(" 1: 82").append(S_NEWLINE);
builder.append(" 2: 88").append(S_NEWLINE);
builder.append(" default: 91").append(S_NEWLINE);
builder.append(" }").append(S_NEWLINE);
builder.append("76: aload_1 ").append(S_NEWLINE);
builder.append("77: astore 4").append(S_NEWLINE);
builder.append("79: goto 91").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(9, instructions.size());
BytecodeInstruction i47 = instructions.get(4);
assertEquals(47, i47.getOffset());
assertEquals(Opcode.IREM, i47.getOpcode());
assertEquals(false, i47.hasParameters());
BytecodeInstruction i76 = instructions.get(6);
assertEquals(76, i76.getOffset());
assertEquals(Opcode.ALOAD_1, i76.getOpcode());
assertEquals(false, i76.hasParameters());
}
@Test
public void testParseBytecodeRegressionLookupSwitch()
{
StringBuilder builder = new StringBuilder();
builder.append("0: lconst_0").append(S_NEWLINE);
builder.append("1: lstore_2").append(S_NEWLINE);
builder.append("2: iconst_0").append(S_NEWLINE);
builder.append("3: lookupswitch { // -1 to 5").append(S_NEWLINE);
builder.append(" -1: 100").append(S_NEWLINE);
builder.append(" 0: 101").append(S_NEWLINE);
builder.append(" 1: 102").append(S_NEWLINE);
builder.append(" 2: 103").append(S_NEWLINE);
builder.append(" 3: 104").append(S_NEWLINE);
builder.append(" 4: 105").append(S_NEWLINE);
builder.append(" 5: 106").append(S_NEWLINE);
builder.append(" default: 107").append(S_NEWLINE);
builder.append("}").append(S_NEWLINE);
builder.append("99: lstore_2").append(S_NEWLINE);
List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(builder.toString());
assertEquals(5, instructions.size());
BytecodeInstruction i3 = instructions.get(3);
assertEquals(3, i3.getOffset());
assertEquals(Opcode.LOOKUPSWITCH, i3.getOpcode());
assertEquals(true, i3.hasParameters());
assertEquals(1, i3.getParameters().size());
IBytecodeParam paramI0 = i3.getParameters().get(0);
assertTrue(paramI0 instanceof BCParamSwitch);
}
// used in next test
public int add(int x, int y)
{
return x + y;
}
@Test
public void testLineNumberTable() throws ClassNotFoundException
{
String[] lines = new String[] {
"Classfile TestBytecodeLoader.class",
" Last modified 18-May-2014; size 426 bytes",
" MD5 checksum d8d0af7620175f82d2c5c753b493196f",
" Compiled from \"TestBytecodeLoader.java\"",
"public class org.adoptopenjdk.jitwatch.test.TestBytecodeLoader",
" SourceFile: \"TestBytecodeLoader.java\"",
" minor version: 0",
" major version: 51",
" flags: ACC_PUBLIC, ACC_SUPER",
"Constant pool:",
" #1 = Methodref #3.#18 // java/lang/Object.\"<init>\":()V",
" #2 = Class #19 // org/adoptopenjdk/jitwatch/test/TestBytecodeLoader",
" #3 = Class #20 // java/lang/Object",
" #4 = Utf8 <init>",
" #5 = Utf8 ()V",
" #6 = Utf8 Code",
" #7 = Utf8 LineNumberTable",
" #8 = Utf8 LocalVariableTable",
" #9 = Utf8 this",
" #10 = Utf8 Lorg/adoptopenjdk/jitwatch/test/TestBytecodeLoader;",
" #11 = Utf8 add",
" #12 = Utf8 (II)I",
" #13 = Utf8 a",
" #14 = Utf8 I",
" #15 = Utf8 b",
" #16 = Utf8 SourceFile",
" #17 = Utf8 TestBytecodeLoader.java",
" #18 = NameAndType #4:#5 // \"<init>\":()V",
" #19 = Utf8 org/adoptopenjdk/jitwatch/test/TestBytecodeLoader",
" #20 = Utf8 java/lang/Object",
"{",
" public org.adoptopenjdk.jitwatch.test.TestBytecodeLoader();",
" flags: ACC_PUBLIC",
" Code:",
" stack=1, locals=1, args_size=1",
" 0: aload_0 ",
" 1: invokespecial #1 // Method java/lang/Object.\"<init>\":()V",
" 4: return ",
" LineNumberTable:",
" line 3: 0",
" LocalVariableTable:",
" Start Length Slot Name Signature",
" 0 5 0 this Lorg/adoptopenjdk/jitwatch/test/TestBytecodeLoader;",
"",
" public int add(int, int);",
" flags: ACC_PUBLIC",
" Code:",
" stack=2, locals=3, args_size=3",
" 0: iload_1 ",
" 1: iload_2 ",
" 2: iadd ",
" 3: ireturn ",
" LineNumberTable:",
" line 7: 0",
" LocalVariableTable:",
" Start Length Slot Name Signature",
" 0 4 0 this Lorg/adoptopenjdk/jitwatch/test/TestBytecodeLoader;",
" 0 4 1 a I",
" 0 4 2 b I",
"}" };
IMetaMember member = UnitTestUtil.createTestMetaMember(getClass().getName(), "add", new Class<?>[] { int.class, int.class },
int.class);
ClassBC classBytecode = BytecodeLoader.parse(getClass().getName(), lines, false);
MemberBytecode memberBytecode = classBytecode.getMemberBytecode(member);
assertNotNull(memberBytecode);
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();
assertEquals(4, instructions.size());
LineTable lineTable = memberBytecode.getLineTable();
assertEquals(1, lineTable.size());
LineTableEntry entry = lineTable.getEntryForSourceLine(7);
int offset = entry.getBytecodeOffset();
assertEquals(0, offset);
JITDataModel model = new JITDataModel();
MetaClass metaClass = UnitTestUtil.createMetaClassFor(model, getClass().getName());
IMetaMember constructor = metaClass.getFirstConstructor();
MemberBytecode memberBytecode2 = classBytecode.getMemberBytecode(constructor);
assertNotNull(memberBytecode2);
List<BytecodeInstruction> instructions2 = memberBytecode2.getInstructions();
assertEquals(3, instructions2.size());
LineTable lineTable2 = memberBytecode2.getLineTable();
LineTableEntry entry2 = lineTable2.getEntryForSourceLine(3);
int offset2 = entry2.getBytecodeOffset();
assertEquals(0, offset2);
}
// used in next test
public char getChar(char[] chars, int index)
{
try
{
return chars[index];
}
catch (ArrayIndexOutOfBoundsException e)
{
return '*';
}
}
@Test
public void testExceptionTable() throws ClassNotFoundException
{
String[] lines = new String[] {
"Classfile TestBytecodeLoader.class",
" Last modified 18-May-2014; size 426 bytes",
" MD5 checksum d8d0af7620175f82d2c5c753b493196f",
" Compiled from \"TestBytecodeLoader.java\"",
"public class org.adoptopenjdk.jitwatch.test.TestBytecodeLoader",
" SourceFile: \"TestBytecodeLoader.java\"",
" minor version: 0",
" major version: 51",
" flags: ACC_PUBLIC, ACC_SUPER",
"Constant pool:",
" #1 = Methodref #3.#18 // java/lang/Object.\"<init>\":()V",
" #2 = Class #19 // org/adoptopenjdk/jitwatch/test/TestBytecodeLoader",
" #3 = Class #20 // java/lang/Object",
" #4 = Utf8 <init>",
" #5 = Utf8 ()V",
" #6 = Utf8 Code",
" #7 = Utf8 LineNumberTable",
" #8 = Utf8 LocalVariableTable",
" #9 = Utf8 this",
" #10 = Utf8 Lorg/adoptopenjdk/jitwatch/test/TestBytecodeLoader;",
" #11 = Utf8 add",
" #12 = Utf8 (II)I",
" #13 = Utf8 a",
" #14 = Utf8 I",
" #15 = Utf8 b",
" #16 = Utf8 SourceFile",
" #17 = Utf8 TestBytecodeLoader.java",
" #18 = NameAndType #4:#5 // \"<init>\":()V",
" #19 = Utf8 org/adoptopenjdk/jitwatch/test/TestBytecodeLoader",
" #20 = Utf8 java/lang/Object",
"{",
" public org.adoptopenjdk.jitwatch.test.TestBytecodeLoader();",
" flags: ACC_PUBLIC",
" Code:",
" stack=1, locals=1, args_size=1",
" 0: aload_0 ",
" 1: invokespecial #1 // Method java/lang/Object.\"<init>\":()V",
" 4: return ",
" LineNumberTable:",
" line 3: 0",
" LocalVariableTable:",
" Start Length Slot Name Signature",
" 0 5 0 this Lorg/adoptopenjdk/jitwatch/test/TestBytecodeLoader;",
"",
" public char getChar(char[], int);",
"descriptor: ([CI)C",
"flags: ACC_PUBLIC",
"Code:",
" stack=2, locals=4, args_size=3",
" 0: aload_1",
" 1: iload_2",
" 2: caload",
" 3: ireturn",
" 4: astore_3",
" 5: bipush 42",
" 7: ireturn",
" Exception table:",
" from to target type",
" 0 3 4 Class java/lang/ArrayIndexOutOfBoundsException",
" LineNumberTable:",
" line 31: 0",
" line 33: 4",
" line 35: 5",
" LocalVariableTable:",
" Start Length Slot Name Signature",
" 5 3 3 e Ljava/lang/ArrayIndexOutOfBoundsException;",
" 0 8 0 this LHotThrow;",
" 0 8 1 chars [C",
" 0 8 2 index I",
" StackMapTable: number_of_entries = 1",
" frame_type = 68 /* same_locals_1_stack_item */",
" stack = [ class java/lang/ArrayIndexOutOfBoundsException ]",
"}" };
IMetaMember member = UnitTestUtil.createTestMetaMember(getClass().getName(), "getChar",
new Class<?>[] { char[].class, int.class }, char.class);
ClassBC classBytecode = BytecodeLoader.parse(getClass().getName(), lines, false);
MemberBytecode memberBytecode = classBytecode.getMemberBytecode(member);
assertNotNull(memberBytecode);
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();
assertEquals(7, instructions.size());
LineTable lineTable = memberBytecode.getLineTable();
assertEquals(3, lineTable.size());
ExceptionTable exceptionTable = memberBytecode.getExceptionTable();
assertEquals(1, exceptionTable.size());
ExceptionTableEntry entry = exceptionTable.getEntries().get(0);
assertEquals(0, entry.getFrom());
assertEquals(3, entry.getTo());
assertEquals(4, entry.getTarget());
assertEquals("java/lang/ArrayIndexOutOfBoundsException", entry.getType());
assertEquals(entry, exceptionTable.getEntryForBCI(2));
}
@Test
public void testClassFileVersion()
{
String[] lines = new String[] {
"public class org.adoptopenjdk.jitwatch.demo.MakeHotSpotLog",
"SourceFile: \"MakeHotSpotLog.java\"",
"minor version: 1",
"major version: 51",
"flags: ACC_PUBLIC, ACC_SUPER" };
ClassBC classBytecode = BytecodeLoader.parse("org.adoptopenjdk.jitwatch.demo.MakeHotSpotLog", lines, false);
assertEquals(1, classBytecode.getMinorVersion());
assertEquals(51, classBytecode.getMajorVersion());
}
@Test
public void testClassFileVersionWithRuntimeAnnotations()
{
String[] lines = new String[] {
"public class org.adoptopenjdk.jitwatch.demo.MakeHotSpotLog",
"SourceFile: \"MakeHotSpotLog.java\"",
" RuntimeVisibleAnnotations:",
" 0: #49(#50=e#51.#52)",
" 0: #49(#50=e#51.#52)",
" 1: #53(#50=[e#54.#55])",
" 2: #56(#50=e#57.#58)",
"minor version: 1",
"major version: 51",
"flags: ACC_PUBLIC, ACC_SUPER" };
ClassBC classBytecode = BytecodeLoader.parse("org.adoptopenjdk.jitwatch.demo.MakeHotSpotLog", lines, false);
assertEquals(1, classBytecode.getMinorVersion());
assertEquals(51, classBytecode.getMajorVersion());
}
@Test
public void testRegressionJMHSampleWithRuntimeAnnotations()
{
String bcSig = "public void measureWrong();";
String[] lines = new String[] {
bcSig,
" descriptor: ()V",
" flags: ACC_PUBLIC",
" Code:",
" stack=2, locals=1, args_size=1",
" 0: aload_0 ",
" 0: aload_0 ",
" 1: getfield #4 // Field x:D",
" 4: invokestatic #5 // Method java/lang/Math.log:(D)D",
" 7: pop2 ",
" 8: return ",
" LineNumberTable:",
" line 65: 0",
" line 66: 8",
" LocalVariableTable:",
" Start Length Slot Name Signature",
" 0 9 0 this Lorg/openjdk/jmh/samples/JMHSample_08_DeadCode;",
" RuntimeVisibleAnnotations:",
" 0: #35()",
" 0: #35()" };
ClassBC classBytecode = BytecodeLoader.parse(getClass().getName(), lines, false);
MemberSignatureParts msp = MemberSignatureParts.fromBytecodeSignature(getClass().getName(), bcSig);
MemberBytecode memberBytecode = classBytecode.getMemberBytecodeForSignature(msp);
assertNotNull(memberBytecode);
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();
assertEquals(6, instructions.size());
int pos = 0;
BytecodeInstruction i0 = instructions.get(pos++);
assertEquals(0, i0.getOffset());
assertEquals(Opcode.ALOAD_0, i0.getOpcode());
assertEquals(false, i0.hasParameters());
assertEquals(0, i0.getParameters().size());
BytecodeInstruction i1 = instructions.get(pos++);
assertEquals(0, i1.getOffset());
assertEquals(Opcode.ALOAD_0, i1.getOpcode());
assertEquals(false, i1.hasParameters());
assertEquals(0, i1.getParameters().size());
BytecodeInstruction i2 = instructions.get(pos++);
assertEquals(1, i2.getOffset());
assertEquals(Opcode.GETFIELD, i2.getOpcode());
assertEquals(true, i2.hasParameters());
assertEquals(1, i2.getParameters().size());
BytecodeInstruction i3 = instructions.get(pos++);
assertEquals(4, i3.getOffset());
assertEquals(Opcode.INVOKESTATIC, i3.getOpcode());
assertEquals(true, i3.hasParameters());
assertEquals(1, i3.getParameters().size());
BytecodeInstruction i4 = instructions.get(pos++);
assertEquals(7, i4.getOffset());
assertEquals(Opcode.POP2, i4.getOpcode());
assertEquals(false, i4.hasParameters());
assertEquals(0, i4.getParameters().size());
BytecodeInstruction i5 = instructions.get(pos++);
assertEquals(8, i5.getOffset());
assertEquals(Opcode.RETURN, i5.getOpcode());
assertEquals(false, i5.hasParameters());
assertEquals(0, i5.getParameters().size());
LineTable lineTable = memberBytecode.getLineTable();
assertEquals(2, lineTable.size());
assertEquals(0, lineTable.getEntryForSourceLine(65).getBytecodeOffset());
assertEquals(8, lineTable.getEntryForSourceLine(66).getBytecodeOffset());
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(0));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(1));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(2));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(3));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(4));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(5));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(6));
assertEquals(65, lineTable.findSourceLineForBytecodeOffset(7));
assertEquals(66, lineTable.findSourceLineForBytecodeOffset(8));
assertEquals(66, lineTable.findSourceLineForBytecodeOffset(9));
assertEquals(66, lineTable.findSourceLineForBytecodeOffset(100));
}
@Test
public void testStaticInitialiserRegression()
{
String[] lines = new String[] {
" static {};",
" descriptor: ()V",
" flags: ACC_STATIC",
" Code:",
" stack=3, locals=0, args_size=0",
" 0: ldc #149 // class org/adoptopenjdk/jitwatch/loader/BytecodeLoader",
" 2: invokestatic #150 // Method org/slf4j/LoggerFactory.getLogger:(Ljava/lang/Class;)Lorg/slf4j/Logger;",
" 5: putstatic #33 // Field logger:Lorg/slf4j/Logger;",
" 8: new #151 // class java/util/HashMap",
" 11: dup",
" 12: invokespecial #152 // Method java/util/HashMap.\"<init>\":()V",
" 15: putstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 18: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 21: ldc #153 // String Constant pool:",
" 23: getstatic #69 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.CONSTANT_POOL:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection;",
" 26: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 31: pop",
" 32: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 35: ldc #155 // String Code:",
" 37: getstatic #67 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.CODE:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection;",
" 40: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 45: pop",
" 46: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 49: ldc #156 // String LineNumberTable:",
" 51: getstatic #71 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.LINETABLE:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection;",
" 54: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 59: pop",
" 60: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 63: ldc #157 // String LocalVariableTable:",
" 65: getstatic #158 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.LOCALVARIABLETABLE:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection;",
" 68: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 73: pop",
" 74: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 77: ldc #159 // String RuntimeVisibleAnnotations:",
" 79: getstatic #160 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.RUNTIMEVISIBLEANNOTATIONS:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSecti$",
" 82: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 87: pop",
" 88: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 91: ldc #161 // String Exceptions:",
" 93: getstatic #162 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.EXCEPTIONS:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection;",
" 96: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 101: pop",
" 102: getstatic #90 // Field sectionLabelMap:Ljava/util/Map;",
" 105: ldc #163 // String StackMapTable:",
" 107: getstatic #164 // Field org/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection.STACKMAPTABLE:Lorg/adoptopenjdk/jitwatch/loader/BytecodeLoader$BytecodeSection;",
" 110: invokeinterface #154, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
" 115: pop",
" 116: return",
" LineNumberTable:",
" line 30: 0",
" line 37: 8",
" line 41: 18",
" line 42: 32",
" line 43: 46",
" line 44: 60",
" line 45: 74" };
ClassBC classBytecode = BytecodeLoader.parse(getClass().getName(), lines, false);
MemberSignatureParts msp = MemberSignatureParts.fromBytecodeSignature(getClass().getName(),
S_BYTECODE_STATIC_INITIALISER_SIGNATURE);
MemberBytecode memberBytecode = classBytecode.getMemberBytecodeForSignature(msp);
assertNotNull(memberBytecode);
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();
assertEquals(43, instructions.size());
}
public int exampleOverloadedMethod(Object object)
{
return object.hashCode();
}
public int exampleOverloadedMethod(String string)
{
return string.hashCode();
}
private void doTestOverloadedMethod(Class<?> paramClass) throws URISyntaxException
{
String className = getClass().getName();
String methodName = "exampleOverloadedMethod";
IMetaMember member = UnitTestUtil.createTestMetaMember(className, methodName, new Class<?>[] { paramClass }, int.class);
final File currentClassFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
List<String> classPath = new ArrayList<String>();
classPath.add(currentClassFile.toURI().toString());
ClassBC classBytecode = BytecodeLoader.fetchBytecodeForClass(classPath, className, false);
MemberBytecode memberBytecode = classBytecode.getMemberBytecode(member);
assertNotNull(memberBytecode);
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();
assertNotNull(instructions);
assertEquals(3, instructions.size());
}
@Test
public void testExampleOverloadedMethodString() throws URISyntaxException
{
doTestOverloadedMethod(java.lang.String.class);
}
@Test
public void testExampleOverloadedMethodObject() throws URISyntaxException
{
doTestOverloadedMethod(java.lang.Object.class);
}
@Test
public void testSignatureGenericsParser()
{
String line = "Signature: #259 // <K:Ljava/lang/Integer;V:Ljava/lang/String;>Ljava/util/AbstractMap<TK;TV;>;Ljava/util/concurrent/ConcurrentMap<TK;TV;>;Ljava/io/Serializable;";
ClassBC classBytecode = new ClassBC(getClass().getName());
BytecodeLoader.buildClassGenerics(line, classBytecode);
assertEquals(2, classBytecode.getGenericsMap().size());
assertTrue(classBytecode.getGenericsMap().containsKey("K"));
assertEquals("java.lang.Integer", classBytecode.getGenericsMap().get("K"));
assertTrue(classBytecode.getGenericsMap().containsKey("V"));
assertEquals("java.lang.String", classBytecode.getGenericsMap().get("V"));
}
}