本文参考:http://www.vuln.cn/7116

本文参考:《Reverse Engineering for Beginners》Dennis Yurichev著

字符串

字符串也是对象,和其他对象的构造方式相同。(包括数组)

第一个例子

public class stringhello {
	public static void main(String[] args) {
		System.out.println("What is your name?");
		String input = System.console().readLine();
		System.out.println("Hello, " + input);
	}
}

编译

javac stringhello.java

反编译

javap -c -verbose stringhello.class
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String What is your name?
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: invokestatic  #5                  // Method java/lang/System.console:()Ljava/io/Console;
        11: invokevirtual #6                  // Method java/io/Console.readLine:()Ljava/lang/String;
        14: astore_1
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: new           #7                  // class java/lang/StringBuilder
        21: dup
        22: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
        25: ldc           #9                  // String Hello,
        27: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        30: aload_1
        31: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        34: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        37: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: return

部分指令解释

11: invokevirtual #6 // Method java/io/Console.readLine:()Ljava/lang/String; //调用了readline()方法,字符串引用(由用户提供)被存储在栈顶

14: astore_1 //将字符串引用从操作数栈中弹出,保存在索引为1的局部变量中(即input)

25: ldc #9 // String Hello,  //将字符串String Hello,压入栈

27: invokevirtual #10  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;  //使用StringBuilder.append方法,返回一个StringBuilder对象的引用压入栈顶,需要从栈顶弹出两个值,一个是StringBuilder的引用,一个是字符串String Hello,

30: aload_1 //将索引为1的局部变量(即input)压入操作数栈

31: invokevirtual #10  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //使用StringBuilder.append方法,返回一个StringBuilder对象的引用压入栈顶,需要从栈顶弹出两个值,一个是StringBuilder的引用,一个是字符串input变量值

34: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; //使用StringBuilder.toString方法,返回一个String对象的引用压入栈顶,需要从栈顶弹出一个值,是StringBuilder的引用

37: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V  //使用PrintStream.println方法,需要从栈顶弹出一个值,是System.out的引用

可以看到字符串的链接由StringBuilder完成


另外一个例子

public class strings {
	public static char test(String a) {
		return a.charAt(3);
	};

	public static String concat(String a, String b) {
		return a + b;
	}
}

反编译

test方法

  public static char test(java.lang.String);
    descriptor: (Ljava/lang/String;)C
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: iconst_3
         2: invokevirtual #2                  // Method java/lang/String.charAt:(I)C
         5: ireturn

concat方法

  public static java.lang.String concat(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=2
         0: new           #3                  // class java/lang/StringBuilder
         3: dup
         4: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
         7: aload_0
         8: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        11: aload_1
        12: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        15: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        18: areturn

这里的字符串的连接也使用StringBuilder类完成

部分指令解释

0: new  #3 // class java/lang/StringBuilder //创建StringBuilder的引用并压入栈顶

3: dup //复制栈顶值,即StringBuilder的引用

4: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V //弹出1个栈顶值,调用<init>方法初始化


另外一个例子

public class stringhellotwo {
	public static void main(String[] args) {
		String s = "Hello!";
		int n = 123;
		System.out.println("s=" + s + " n=" + n);
	}
}

反编译

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1
         0: ldc           #2                  // String Hello!
         2: astore_1
         3: bipush        123
         5: istore_2
         6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         9: new           #4                  // class java/lang/StringBuilder
        12: dup
        13: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        16: ldc           #6                  // String s=
        18: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: aload_1
        22: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        25: ldc           #8                  // String  n=
        27: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        30: iload_2
        31: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        34: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        40: return

这里的字符串的连接也使用StringBuilder类进行拼接