> org.gradle.api.tasks.compile.CompileOptions.setBootClasspath(Ljava/lang/String;)V * Try: Run
// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 30: iload...":(Ljava/lang/String;I)V 41: astore_3 42: aload_1 43: iload_2 44: new...// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 74: aload...// Method java/io/PrintStream.println:(Ljava/lang/String;)V 89: invokestatic #18...// Method java/io/PrintStream.println:(Ljava/lang/String;)V 122: return } ---- 参考原文: windows命令行中
非 String 对象:通过调用String.valueOf方法,如果是 null 对象,就返回”null”,否则调用对象的toString方法。... ()V ALOAD 1 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder...INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL...java/lang/StringBuilder.toString ()Ljava/lang/String; ASTORE 1 L2 LINENUMBER 29 L2 GETSTATIC java.../String;)V 看了上面的字节码是不是一头雾水?
非 String 对象:通过调用String.valueOf方法,如果是 null 对象,就返回"null",否则调用对象的toString方法。... ()V ALOAD 1 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder...INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL...java/lang/StringBuilder.toString ()Ljava/lang/String; ASTORE 1L2 LINENUMBER 29 L2 GETSTATIC java/lang.../System.out : Ljava/io/PrintStream; ALOAD 1 INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String
非 String 对象:通过调用String.valueOf方法,如果是 null 对象,就返回"null",否则调用对象的toString方法。... ()V ALOAD 1 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder...INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL...java/lang/StringBuilder.toString ()Ljava/lang/String; ASTORE 1 L2 LINENUMBER 29 L2 GETSTATIC java/lang.../System.out : Ljava/io/PrintStream; ALOAD 1 INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String
image.png 事实上这里还有隐藏逻辑,看其中源码,你会发现,卧槽,我都找不到定义jni的方法名,熟悉jni的同学知道,jni方法名是Java+ 全类名 命名,可是你会发觉比如你想找到_start方法.../lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", (void *) IjkMediaPlayer_setDataSourceAndHeaders...}, { "_setOption", "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption...}, { "_getVideoCodecInfo", "()Ljava/lang/String;", (void *) IjkMediaPlayer_getVideoCodecInfo...}, { "_getAudioCodecInfo", "()Ljava/lang/String;", (void *) IjkMediaPlayer_getAudioCodecInfo
":(Ljava/lang/String;)V 9: astore_1 10: aload_1 11: invokevirtual #3...":(Ljava/lang/String;)V 9: ldc #11 // String Miao 11: invokevirtual...":(Ljava/lang/String;)V 9: ldc #15 // String va 11: invokevirtual...1.2 Public的方法都是复制一份数据 String有很多public方法,要想维护这么多方法下的不可变需要付出代价。每次都将创建新的String对象。...如果String是mutable,那么修改属性后,其hashcode也将改变。这样导致在HashMap中找不到原来的value。
":(Ljava/lang/String;)V 9: astore_1 10: new #5 // class...":(Ljava/lang/String;)V 26: invokevirtual #10 // Method java/lang/StringBuilder.append...:(Ljava/lang/String;)Ljava/lang/StringBuilder; 29: new #7 // class java...":(Ljava/lang/String;)V 38: invokevirtual #10 // Method java/lang/StringBuilder.append...:(Ljava/lang/String;)Ljava/lang/StringBuilder; 41: invokevirtual #12 // Method
lang.String> ......省略部分结果.........void set(java.lang.String); descriptor: (Ljava/lang/String;)V flags: Code: stack=,...); descriptor: (Ljava/lang/Object;)V flags: ACC_BRIDGE, ACC_SYNTHETIC Code: stack=,.../String : invokevirtual #3 // Method set:(Ljava/lang/String;)V : return...这个方法就起了一个桥接的作用,它所做的就是把对自身的调用通过invokevirtual指令再调用方法void set(java.lang.String)。 编译器这么做的原因是什么呢?
; #10 = Methodref #53.#54 // java/io/PrintStream.println:(Ljava/lang/String;)V #11.../lang/String;)V #22 = Utf8 args #23 = Utf8 [Ljava/lang/String; #24...Ljava/lang/String;)V #48 = NameAndType #63:#64 // accept:()Ljava/util/function/Consumer...#28:#29 // lambda$main$0:(Ljava/lang/String;)V #76 = Utf8 java/lang/invoke.../lang/String;)V #47 (Ljava/lang/String;)V ?
lang.String> ......省略部分结果.........void set(java.lang.String); descriptor: (Ljava/lang/String;)V flags: Code: stack=0,...); descriptor: (Ljava/lang/Object;)V flags: ACC_BRIDGE, ACC_SYNTHETIC Code: stack=2.../String 5: invokevirtual #3 // Method set:(Ljava/lang/String;)V 8:...这个方法就起了一个桥接的作用,它所做的就是把对自身的调用通过invokevirtual指令再调用方法void set(java.lang.String)。 **编译器这么做的原因是什么呢?
#43.#44 // java/io/PrintStream.println:(Ljava/lang/String;)V // Jathonkatu 方法符号引用 调用printStream...$0 // Jathonkatu 方法名 #26 = Utf8 (Ljava/lang/String;)V // Jathonkatu String变量值 #27...lang/String;)V #36 = MethodType #26 // (Ljava/lang/String;)V // Jathonkatu 方法类型...[]); //Jathonkatu main方法 descriptor: ([Ljava/lang/String;)V // Jathonkatu 描述符 flags: ACC_PUBLIC...$main$0:(Ljava/lang/String;)V #36 (Ljava/lang/String;)V
/lang/String;Ljava/lang/String;)I", false); mv.visitInsn(Opcodes.POP); } @Override.../lang/String;Ljava/lang/String;)I", false); mv.visitInsn(Opcodes.POP); super.onMethodExit...MethodVisitor methodVisitor; AnnotationVisitor annotationVisitor0; classWriter.visit(V1.../lang/String;Ljava/lang/String;)I", false); methodVisitor.visitInsn(POP); Label.../lang/String;Ljava/lang/String;)I", false); methodVisitor.visitInsn(POP); 然后将其放入到onMethodExit函数中,就可以了
---- -v 的意思就是打印详细的所以的附加信息,一些本地方法栈针的引用,出栈 入栈等信息。一些版本号啥的。 ? 将其导入一个txt 文件便于观看。...":(Ljava/lang/String;)V #25 = NameAndType #5:#26 // "":(Ljava/lang/String...;)V #26 = Utf8 (Ljava/lang/String;)V #27 = Fieldref #28.#30 // java...":(Ljava/lang/String;)V #40 = Methodref #33.#41 // java/lang/StringBuilder.append...我们开始讲方法一。 ? 方法名称main 方法, 返回类型string , 访问修饰符public static 的。
} 当调用intern方法时,如果常量池已经包含一个equals此String对象的字符串,则返回池中的字符串 当调用intern方法时,如果常量池没有一个equals此...":(Ljava/lang/String;)V #5 = Methodref #2.#25 // java/lang/String.intern:()...":(Ljava/lang/String;)V #5 = String #28 // cat #6 = InvokeDynamic...$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang...":(Ljava/lang/String;)V 9: new #2 // class java/lang/String
v3}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; move-result-object v3...invoke-direct {v2, v3}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V const-string v3,...}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; move-result-object v4...v3 invoke-static {v2, v3}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I .line...:Ljava/lang/String; return-object v0 .end method 调用方法: invoke-static {p2}, Lnet/iaround/connector
前言 在之前的面试经历中,对于String的考察还是挺频繁的,大致考察以下几个知识点: String 常量池 new String() == 和 equals 的区别 native 方法 String.intern...我去证实了,发现确实调用了 append 方法,但是当时没有 调用toString()方法,我很疑惑。...":()V # = Methodref #.# // java/lang/StringBuilder.append:(Ljava/lang/String.../test/Main; # = Utf8 main # = Utf8 ([Ljava/lang/String;)V # = Utf8...; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC
:(Ljava/lang/String;)V 28: return 完整的class文件 Classfile /home/zsh/workplace/idea/leetcode/out....#62 // java/io/PrintStream.println:(Ljava/lang/String;)V #11 = Class #63...= Utf8 Ljava/lang/Object;Ljava/lang/ComparableLjava/lang/String;>;Ljava/io/Serializable...(Ljava/lang/String;)Ljava/lang/StringBuilder; #78 = Utf8 (I)Ljava/lang/StringBuilder;...:(Ljava/lang/String;)V 28: return LineNumberTable: line 10: 0 line 11:
java/io/PrintStream.println (Ljava/lang/String;)V L4 LINENUMBER 13 L4 GETSTATIC java/lang/System.out...java/io/PrintStream.println (Ljava/lang/String;)V L10 LINENUMBER 20 L10 GETSTATIC java/lang/...java/io/PrintStream.println (Ljava/lang/String;)V // 4....java/io/PrintStream.println (Ljava/lang/String;)V L10 LINENUMBER 20 L10 GETSTATIC java/lang/...(Ljava/lang/String;)V L12 LINENUMBER 20 L12 GETSTATIC java/lang/System.out : Ljava/io/PrintStream
/lang/Object; 2.4、解读方法字节码 public static void main(java.lang.String[]); descriptor:([...Ljava/lang/String;)V //方法描述,V表示该方法的放回值为void flags:ACC_PUBLIC,ACC_STATIC // 方法修饰符,public...":()V #10 = Methodref #8.#43 // java/lang/StringBuilder.append: (Ljava/lang/String;)Ljava/lang/.../lang/String;)V #24 = Utf8 args #25 = Utf8 [Ljava/lang/String; #26 = Utf8 m1 #27 = Utf8 s1 #28 = Utf8...println: (Ljava/lang/String;)V #52 = Utf8 java/lang/Object #53 = Utf8 java/lang/String #54 = Utf8 append