public class Foo { public static void main(String[] args) { boolean flag = true; if (flag) System.out.println("Hello, Java!"); if (flag == true) System.out.println("Hello, JVM!"); } }
$ javac Foo.java $ java Foo Hello, Java! Hello, JVM!
# jasm与javap的输出比较类似 $ java -cp ./asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.bak
$ tail -n 23 Foo.jasm.bak | head -n 21 public static Method main:"([Ljava/lang/String;)V" stack 2 locals 2 { iconst_1; istore_1; iload_1; ifeq L14; # 出栈int,如果等于0时跳转;实际为1,无需跳转 getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ldc String "Hello, Java!"; invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; L14: stack_frame_type append; locals_map int; iload_1; iconst_1; if_icmpne L27; # 出栈2个int,如果不相等时跳转;实际为1和1,无需跳转 getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ldc String "Hello, JVM!"; invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; L27: stack_frame_type same; return; }
使用awk命令修改字节码
$ awk 'NR==1,/iconst_1/{sub(/iconst_1/, "iconst_2")} 1' Foo.jasm.bak > Foo.jasm $ tail -n 23 Foo.jasm.bak | head -n 21 public static Method main:"([Ljava/lang/String;)V" stack 2 locals 2 { iconst_2; # iconst_1 -> iconst_2 istore_1; iload_1; ifeq L14; # 出栈int,如果等于0时跳转;实际为1,无需跳转 getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ldc String "Hello, Java!"; invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; L14: stack_frame_type append; locals_map int; iload_1; iconst_1; if_icmpne L27; # 出栈2个int,如果不相等时跳转;实际为1和2,需跳转 getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ldc String "Hello, JVM!"; invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; L27: stack_frame_type same; return; }
$ java -cp ./asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm $ java Foo Hello, Java!
private static String floatToHexIntBits(float f) { return Integer.toHexString(Float.floatToIntBits(f)); }
float z1 = +0.0F; // +0.0F float z2 = -0.0F; // -0.0F log.info("{}", floatToHexIntBits(z1)); // 0 log.info("{}", floatToHexIntBits(z2)); // 0x80000000 log.info("{}", z1 == z2); // 两个0对应的内存数值不同,但+0.0F == -0.0F
public static final float POSITIVE_INFINITY = 1.0f / 0.0f; public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; log.info("{}", floatToHexIntBits(Float.POSITIVE_INFINITY)); // 0x7F800000 log.info("{}", floatToHexIntBits(Float.NEGATIVE_INFINITY)); // 0XFF800000
float f = 1.0F; log.info("{}", floatToHexIntBits(NaN)); // 0x7FC00000 log.info("{}", NaN < f); // false log.info("{}", NaN >= f); // false log.info("{}", NaN != f); // true log.info("{}", NaN == f); // false log.info("{}", NaN == NaN); // false
@Slf4j @Data public class User { private boolean sex; public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); Unsafe unsafe = (Unsafe) field.get(null); User user = new User(); Field sexField = User.class.getDeclaredField("sex"); unsafe.putByte(user, unsafe.objectFieldOffset(sexField), (byte) 2); log.info("{}", user.isSex()); // 10 -> 0 , false unsafe.putByte(user, unsafe.objectFieldOffset(sexField), (byte) 3); log.info("{}", user.isSex()); // 11 -> 1 , true } }
转载请注明出处:http://zhongmingmao.me/2018/12/15/jvm-basic-native-type/
访问原文「基本类型」获取最佳阅读体验并参与讨论