#1 = Methodref          #9.#25         // java/lang/Object."<init>":()V

#2 = InvokeDynamic #0:#30 // #0:log:()LLambda$Logger;
#3 = String #31 // HelloWorld
#4 = Methodref #8.#32 // Lambda.logDebug:(LLambda$Logger;Ljava/lang/String;)V
#5 = InterfaceMethodref #10.#33 // Lambda$Logger.log:(Ljava/lang/String;)V
#6 = Fieldref #34.#35 // java/lang/System.out:Ljava/io/PrintStream;
#7 = Methodref #36.#37 // java/io/PrintStream.println:(Ljava/lang/String;)V
#8 = Class #38 // Lambda
#9 = Class #39 // java/lang/Object
#10 = Class #40 // Lambda$Logger
#11 = Utf8 Logger
#12 = Utf8 InnerClasses
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 Code
#16 = Utf8 LineNumberTable
#17 = Utf8 main
#18 = Utf8 ([Ljava/lang/String;)V
#19 = Utf8 logDebug
#20 = Utf8 (LLambda$Logger;Ljava/lang/String;)V
#21 = Utf8 lambda$main$0
#22 = Utf8 (Ljava/lang/String;)V
#23 = Utf8 SourceFile
#24 = Utf8 Lambda.java
#25 = NameAndType #13:#14 // "<init>":()V
#26 = Utf8 BootstrapMethods
#27 = MethodHandle #6:#41 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#28 = MethodType #22 // (Ljava/lang/String;)V
#29 = MethodHandle #6:#42 // invokestatic Lambda.lambda$main$0:(Ljava/lang/String;)V
#30 = NameAndType #43:#44 // log:()LLambda$Logger;
#31 = Utf8 HelloWorld
#32 = NameAndType #19:#20 // logDebug:(LLambda$Logger;Ljava/lang/String;)V
#33 = NameAndType #43:#22 // log:(Ljava/lang/String;)V
#34 = Class #45 // java/lang/System
#35 = NameAndType #46:#47 // out:Ljava/io/PrintStream;
#36 = Class #48 // java/io/PrintStream
#37 = NameAndType #49:#22 // println:(Ljava/lang/String;)V
#38 = Utf8 Lambda
#39 = Utf8 java/lang/Object
#40 = Utf8 Lambda$Logger
#41 = Methodref #50.#51 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#42 = Methodref #8.#52 // Lambda.lambda$main$0:(Ljava/lang/String;)V
#43 = Utf8 log
#44 = Utf8 ()LLambda$Logger;
#45 = Utf8 java/lang/System
#46 = Utf8 out
#47 = Utf8 Ljava/io/PrintStream;
#48 = Utf8 java/io/PrintStream
#49 = Utf8 println
#50 = Class #53 // java/lang/invoke/LambdaMetafactory
#51 = NameAndType #54:#57 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#52 = NameAndType #21:#22 // lambda$main$0:(Ljava/lang/String;)V
#53 = Utf8 java/lang/invoke/LambdaMetafactory
#54 = Utf8 metafactory
#55 = Class #59 // java/lang/invoke/MethodHandles$Lookup
#56 = Utf8 Lookup
#57 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#58 = Class #60 // java/lang/invoke/MethodHandles
#59 = Utf8 java/lang/invoke/MethodHandles$Lookup
#60 = Utf8 java/lang/invoke/MethodHandles
{
public Lambda();
descriptor: ()V
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 1: 0

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: invokedynamic #2, 0 // InvokeDynamic #0:log:()LLambda$Logger;
5: ldc #3 // String HelloWorld
7: invokestatic #4 // Method logDebug:(LLambda$Logger;Ljava/lang/String;)V
10: return
LineNumberTable:
line 3: 0
line 4: 10

static void logDebug(Lambda$Logger, java.lang.String);
descriptor: (LLambda$Logger;Ljava/lang/String;)V
flags: ACC_STATIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokeinterface #5, 2 // InterfaceMethod Lambda$Logger.log:(Ljava/lang/String;)V
7: return
LineNumberTable:
line 7: 0
line 8: 7
}
SourceFile: "Lambda.java"
InnerClasses:
static #11= #10 of #8; //Logger=class Lambda$Logger of class Lambda
public static final #56= #55 of #58; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #27 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#28 (Ljava/lang/String;)V
#29 invokestatic Lambda.lambda$main$0:(Ljava/lang/String;)V
#28 (Ljava/lang/String;)V


在上面的详细字节码信息中,有两个重要信息需要我们注意:

**`major version: 52`**

主版本号是 `52` 对应的是 `JDK 1.8`。

**`invokedynamic` 指令**

`invokedynamic` 在 `Java7` 开始提出来,但是实际上 `javac` 并不支持生成 `invokedynamic`。在 `Java 8` 中,`javac` 能够生成 `invokedynamic` 指令, 比如 `lambda` 表达式。

#### 2.2 dx 指令打包

首先我们采用 `buildToolsVersion = 22.0.1` 版本来编译上面的 `class` 文件。

$/Users/dengshiwei/Library/Android/sdk/build-tools/22.0.1/dx –dex *.class


出错了!

UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)
at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:472)
at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)
at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)
at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)
at com.android.dx.command.dexer.Main.processClass(Main.java:704)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:673)
at com.android.dx.command.dexer.Main.access$300(Main.java:83)
at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:602)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:170)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:632)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:510)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:280)
at com.android.dx.command.dexer.Main.run(Main.java:246)

最后

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!

Android D8 编译器 和 R8 工具,Android开发框架

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

Android D8 编译器 和 R8 工具,Android开发框架