Java特种兵 - JVM 跨平台与字节码原理,Reading Notes
用到 JVM 的场景
Out of memory 时,团队高手不在
系统服务器架构,老大问你 投入多少服务器成本,VM 分配多大, 如何分配?
1. javap 命令
通过这种方式认知比 Java 更低一个抽象层次的逻辑,虚指令有时候更好解释问题。
1 2 3 4 5 6 7 public class StringTest { public static void test1 () { String a = "a" + "b" + 1 ; String b = "ab1" ; System.out.println(a == b); } }
1 2 3 4 5 6 7 8 9 10 ➜ p3jvm git:(master) ✗ pwd /Users/hp/ghome/github/language/java/jsarms/p3jvm ➜ p3jvm git:(master) ✗ javac Usage: javac <options> <source files> where possible options include: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source } Generate only some debugging info -nowarn Generate no warnings -verbose Output messages about what the compiler is doing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 ➜ p3jvm git:(master) ✗ javac -g:vars,lines StringTest.java ➜ p3jvm git:(master) ✗ javap -verbose StringTest Classfile /Users/hp/ghome/github/language/java/jsarms/p3jvm/StringTest.class Last modified Aug 16, 2016; size 559 bytes MD5 checksum 772d18512cb982c953e7db8c72522918 public class StringTest minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: // 以上是 Constant pool, 仅仅是陈列操作,并没有开始执行任务,看下面开始 { public StringTest(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 // 所有方法都会有。 // stack 为栈顶的单位大小 (每个大小为 1 slot,4 byte) // locals=1,非静态方法,本地变量增加 this 0: aload_0 1: invokespecial 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LStringTest; public static void test1(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=3, locals=2, args_size=0 // stack=3,本地栈slot个数为3,String需要load,String.out 占用一个再。当对比发生 boolean 时,两个String引用栈顶pop // locals=2, 因为只有两个 String // args_size=0,方法没有入口参数 0: ldc // 引用常量池内容 2: astore_0 // 将栈顶引用值,写入第 1 个 slot 所在的本地变量 3: ldc 5: astore_1 6: getstatic // 获取静态域,放入栈顶,此时静态域是 System.out 对象 9: aload_0 10: aload_1 11: if_acmpne 18 14: iconst_1 15: goto 19 18: iconst_0 19: invokevirtual 22: return LineNumberTable: line 4: 0 line 5: 3 line 6: 6 line 7: 22 LocalVariableTable: Start Length Slot Name Signature 3 20 0 a Ljava/lang/String; 6 17 1 b Ljava/lang/String; // 本地变量列表 LocalVariableTable. from javac -g:vars StackMapTable: number_of_entries = 2 frame_type = 255 /* full_frame */ offset_delta = 18 locals = [ class java/lang/String, class java/lang/String ] stack = [ class java/io/PrintStream ] frame_type = 255 /* full_frame */ offset_delta = 0 locals = [ class java/lang/String, class java/lang/String ] stack = [ class java/io/PrintStream, int ] } ➜ p3jvm git:(master) ✗
2. Java 字节码结构
javac 命令本身只是一个引导器,它引导编译器程序的运行。编译器本身是一个java程序 com.sun.tools.javac.main.JavaCompiler
, 该类完成 java 源文件 的 Parser、Annotation process、检查、泛型处理、语法转换等,最终胜出 Class 文件。
Java 字节码文件主体结构:
Class 文件头部
Constant pool
当前Clas的描述信息
属性列表
方法列表
…
Checking if Disqus is accessible...