ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
链接:https://juejin.im/post/589834a20ce4630056097a56
每个字段含义http://blog.csdn.net/u012422829/article/details/46633515
常量池https://www.cnblogs.com/lcchuguo/p/4470835.html
https://github.com/HalfStackDeveloper/ClassReader/blob/master/src/com/wangxiandeng/classreader/basicinfo/MemberInfo.java
//From javassist.bytecode.ClassFile
private void read(DataInputStream in) throws IOException {
int i, n;
int magic = in.readInt();
if (magic != 0xCAFEBABE)
throw new IOException("bad magic number: " + Integer.toHexString(magic));
minor = in.readUnsignedShort();
major = in.readUnsignedShort();
constPool = new ConstPool(in);
accessFlags = in.readUnsignedShort();
thisClass = in.readUnsignedShort();
constPool.setThisClassInfo(thisClass);
superClass = in.readUnsignedShort();
n = in.readUnsignedShort();
if (n == 0)
interfaces = null;
else {
interfaces = new int[n];
for (i = 0; i < n; ++i)
interfaces[i] = in.readUnsignedShort();
}
ConstPool cp = constPool;
n = in.readUnsignedShort();
fields = new ArrayList();
for (i = 0; i < n; ++i)
addField2(new FieldInfo(cp, in));
n = in.readUnsignedShort();
methods = new ArrayList();
for (i = 0; i < n; ++i)
addMethod2(new MethodInfo(cp, in));
attributes = new ArrayList();
n = in.readUnsignedShort();
for (i = 0; i < n; ++i)
addAttribute(AttributeInfo.read(cp, in));
thisclassname = constPool.getClassInfo(thisClass);
}
Class文件的解析过程,简版如上,完全是根据ClassFile.java定义的数据格式解析的。常量池存放了当前类的所有字符信息,真的是全部的字符信息,比如String字符串、方法名、方法格式、属性名、属性类型、方法体内依赖的类。常量池的作用是合并重复项减少文件大小。也是个序列化与反序列化的过程,如下所示:
------FragmentTransaction ft; 属性-------
18 Field #45, name&type #104
104 NameAndType #52, type #53
52 UTF8 "ft"
53 UTF8 "Landroid/support/v4/app/FragmentTransaction;"
45 Class #134
134 UTF8 "com/mrzhang/component/MainActivity"
MainActivity ft FragmentTransaction 参数类型因为有内部类,所以要指定是当前属性属于哪个类
------ft.remove(fragment).commit(); 方法--------
方法(常量池中某条的类型)——所属类——方法入参类型和返回类型
19 Method #105, name&type #106
20 Method #105, name&type #107
106 NameAndType #152, type #153
107 NameAndType #154, type #155
152 UTF8 "remove"
153 UTF8 "(Landroid/support/v4/app/Fragment;)Landroid/support/v4/app/FragmentTransaction;"
154 UTF8 "commit"
155 UTF8 "()I"
105 Class #151
151 UTF8 "android/support/v4/app/FragmentTransaction"
案例1:
.method protected onResume()V
.locals 2
.prologue
.line 52
invoke-super {p0}, Lcom/meituan/sankuai/erpboss/modules/BaseStatisticsActivity;->onResume()V
.line 53
invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
move-result-wide v0
iput-wide v0, p0, Lcom/meituan/sankuai/erpboss/modules/cashier/CashierReportActivity;->mStartTime:J
.line 54
return-void
.end method
案例2:
.method private static get$Lambda(Lcom/meituan/sankuai/erpboss/component/PickerDataManager;Landroid/content/Context;)Lrx/functions/Action1;
.locals 1
new-instance v0, Lcom/meituan/sankuai/erpboss/component/PickerDataManager$$Lambda$3;
invoke-direct {v0, p0, p1}, Lcom/meituan/sankuai/erpboss/component/PickerDataManager$$Lambda$3;-><init>(Lcom/meituan/sankuai/erpboss/component/PickerDataManager;Landroid/content/Context;)V
return-object v0
.end method
常量池中常量有多种类型Integer、Class、Method、Field、Interface、UTF8、String等。每种类型解析不一样。比如:
2 Method #46, name&type #87
3 Class #89
4 Integer 2130968603
在做类依赖关系管理时,可以扫描Class文件的常量区中的UTF8相关的类全都提取出来,就是当前类的直接依赖汇总,再基于直接类递归分析间接依赖类。
32 Class #121
121 UTF8 "com/mrzhang/component/MainActivity$MyAsyncTask"
100 UTF8 "com/mrzhang/component/MainActivity$1"
71 UTF8 "Lcom/mrzhang/componentservice/readerbook/ReadBookService;"
155 UTF8 "(Landroid/support/v4/app/Fragment;)Landroid/support/v4/app/FragmentTransaction;"
160 UTF8 "java/lang/Class"
178 UTF8 "(Ljava/util/concurrent/Executor;[Ljava/lang/Object;)Landroid/os/AsyncTask;"
175 UTF8 "(I)Ljava/lang/StringBuilder;"
public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);
118 NameAndType #167, type #168
167 UTF8 "add"
168 UTF8 "(ILandroid/support/v4/app/Fragment;)Landroid/support/v4/app/FragmentTransaction;"
观察特征,提取直接依赖的Class文件:
是否包含『/』 ----> 根据";"做分割并去除空格 ----> 去除头部的"(" 或")"或 "L等大写的字符",去除尾部的";" ----> 得到类文件
1 Method #9, name&type #20
2 Method #9, name&type #21
3 String #22
4 String #23
5 Method #24, name&type #25
6 String #26
7 String #27
8 Class #28
9 Class #29
10 UTF8 "<init>"
11 UTF8 "()V"
12 UTF8 "Code"
13 UTF8 "LineNumberTable"
14 UTF8 "LocalVariableTable"
15 UTF8 "this"
16 UTF8 "Lcom/mrzhang/component/application/AppApplication;"
17 UTF8 "onCreate"
18 UTF8 "SourceFile"
19 UTF8 "AppApplication.java"
20 NameAndType #10, type #11
21 NameAndType #17, type #11
22 UTF8 "smarking"
23 UTF8 "begin inject "
24 Class #30
25 NameAndType #31, type #32
26 UTF8 "test getReadBookFragment "
27 UTF8 "test getReadBookFragment MainActivity"
28 UTF8 "com/mrzhang/component/application/AppApplication"
29 UTF8 "android/app/Application"
30 UTF8 "android/util/Log"
31 UTF8 "d"
32 UTF8 "(Ljava/lang/String;Ljava/lang/String;)I"
ClassInfo{constPool=null, thisClass=8, accessFlags=33, superClass=9, interfaces=null, thisClassName='com.mrzhang.component.application.AppApplication', major=51, minor=0}
ClassDog find target in /Users/Smarking/AndroidStudioProjects/newworld/DDComponentForAndroid/app/build/intermediates/classes/debug/com/mrzhang/component/application/AppApplication.class
1 Field #5, name&type #27
2 Method #6, name&type #28
3 String #29
4 Method #30, name&type #31
5 Class #32
6 Class #33
7 Class #35
8 UTF8 "this$0"
9 UTF8 "Lcom/mrzhang/component/MainActivity;"
10 UTF8 "<init>"
11 UTF8 "(Lcom/mrzhang/component/MainActivity;)V"
12 UTF8 "Code"
13 UTF8 "LineNumberTable"
14 UTF8 "LocalVariableTable"
15 UTF8 "this"
16 UTF8 "InnerClasses"
17 UTF8 "Lcom/mrzhang/component/MainActivity$1;"
18 UTF8 "onClick"
19 UTF8 "(Landroid/view/View;)V"
20 UTF8 "v"
21 UTF8 "Landroid/view/View;"
22 UTF8 "SourceFile"
23 UTF8 "MainActivity.java"
24 UTF8 "EnclosingMethod"
25 Class #37
26 NameAndType #38, type #39
27 NameAndType #8, type #9
28 NameAndType #10, type #40
29 UTF8 "com.mrzhang.share.applike.ShareApplike"
30 Class #41
31 NameAndType #42, type #43
32 UTF8 "com/mrzhang/component/MainActivity$1"
33 UTF8 "java/lang/Object"
34 Class #44
35 UTF8 "android/view/View$OnClickListener"
36 UTF8 "OnClickListener"
37 UTF8 "com/mrzhang/component/MainActivity"
38 UTF8 "onCreate"
39 UTF8 "(Landroid/os/Bundle;)V"
40 UTF8 "()V"
41 UTF8 "com/mrzhang/component/componentlib/router/Router"
42 UTF8 "unregisterComponent"
43 UTF8 "(Ljava/lang/String;)V"
44 UTF8 "android/view/View"
ClassInfo{constPool=null, thisClass=5, accessFlags=32, superClass=6, interfaces=[7], thisClassName='com.mrzhang.component.MainActivity$1', major=51, minor=0}
ClassDog find target in /Users/Smarking/AndroidStudioProjects/newworld/DDComponentForAndroid/app/build/intermediates/classes/debug/com/mrzhang/component/MainActivity$1.class
1 Field #14, name&type #45
2 Method #15, name&type #46
3 Long 100
4 padding
5 Method #47, name&type #48
6 Class #49
7 Method #6, name&type #50
8 Class #51
9 Method #15, name&type #52
10 String #53
11 Method #54, name&type #55
12 Method #14, name&type #56
13 Method #14, name&type #57
14 Class #59
15 Class #60
16 UTF8 "this$0"
17 UTF8 "Lcom/mrzhang/component/MainActivity;"
18 UTF8 "<init>"
19 UTF8 "(Lcom/mrzhang/component/MainActivity;)V"
20 UTF8 "Code"
21 UTF8 "LineNumberTable"
22 UTF8 "LocalVariableTable"
23 UTF8 "this"
24 UTF8 "MyAsyncTask"
25 UTF8 "InnerClasses"
26 UTF8 "Lcom/mrzhang/component/MainActivity$MyAsyncTask;"
27 UTF8 "doInBackground"
28 UTF8 "([Ljava/lang/Object;)Ljava/lang/String;"
29 UTF8 "e"
30 UTF8 "Ljava/lang/InterruptedException;"
31 UTF8 "params"
32 UTF8 "[Ljava/lang/Object;"
33 UTF8 "StackMapTable"
34 Class #49
35 UTF8 "onPostExecute"
36 UTF8 "(Ljava/lang/String;)V"
37 UTF8 "s"
38 UTF8 "Ljava/lang/String;"
39 UTF8 "(Ljava/lang/Object;)V"
40 UTF8 "([Ljava/lang/Object;)Ljava/lang/Object;"
41 UTF8 "Signature"
42 UTF8 "Landroid/os/AsyncTask<Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;>;"
43 UTF8 "SourceFile"
44 UTF8 "MainActivity.java"
45 NameAndType #16, type #17
46 NameAndType #18, type #61
47 Class #62
48 NameAndType #63, type #64
49 UTF8 "java/lang/InterruptedException"
50 NameAndType #65, type #61
51 UTF8 "java/lang/String"
52 NameAndType #35, type #39
53 UTF8 "zxx"
54 Class #66
55 NameAndType #67, type #68
56 NameAndType #35, type #36
57 NameAndType #27, type #28
58 Class #69
59 UTF8 "com/mrzhang/component/MainActivity$MyAsyncTask"
60 UTF8 "android/os/AsyncTask"
61 UTF8 "()V"
62 UTF8 "java/lang/Thread"
63 UTF8 "sleep"
64 UTF8 "(J)V"
65 UTF8 "printStackTrace"
66 UTF8 "android/util/Log"
67 UTF8 "d"
68 UTF8 "(Ljava/lang/String;Ljava/lang/String;)I"
69 UTF8 "com/mrzhang/component/MainActivity"
ClassInfo{constPool=null, thisClass=14, accessFlags=32, superClass=15, interfaces=null, thisClassName='com.mrzhang.component.MainActivity$MyAsyncTask', major=51, minor=0}
ClassDog find target in /Users/Smarking/AndroidStudioProjects/newworld/DDComponentForAndroid/app/build/intermediates/classes/debug/com/mrzhang/component/MainActivity$MyAsyncTask.class
1 Method #47, name&type #87
2 Method #47, name&type #88
3 Class #90
4 Integer 2130968603
5 Method #46, name&type #92
6 Class #93
7 Integer 2131427414
8 Method #46, name&type #95
9 Class #96
10 Field #46, name&type #97
11 Integer 2131427415
12 Field #46, name&type #98
13 Method #9, name&type #99
14 Class #100
15 Method #14, name&type #101
16 Method #46, name&type #102
17 Field #46, name&type #103
18 Method #46, name&type #104
19 Method #105, name&type #106
20 Field #46, name&type #107
21 Method #108, name&type #109
22 Method #108, name&type #110
23 Method #111, name&type #112
24 Class #113
25 Method #114, name&type #115
26 Method #111, name&type #116
27 Interface #24, name&type #117
28 Integer 2131427416
29 Method #108, name&type #118
30 Method #108, name&type #119
31 Method #47, name&type #120
32 Class #121
33 Method #32, name&type #101
34 Field #122, name&type #123
35 Class #124
36 Class #125
37 Method #36, name&type #87
38 String #126
39 Method #36, name&type #127
40 Method #36, name&type #128
41 Method #36, name&type #129
42 Method #122, name&type #130
43 Method #131, name&type #132
44 String #133
45 Method #111, name&type #134
46 Class #135
47 Class #136
48 Class #137
49 UTF8 "MyAsyncTask"
50 UTF8 "InnerClasses"
51 UTF8 "fragment"
52 UTF8 "Landroid/support/v4/app/Fragment;"
53 UTF8 "ft"
54 UTF8 "Landroid/support/v4/app/FragmentTransaction;"
55 UTF8 "installReadBookBtn"
56 UTF8 "Landroid/widget/Button;"
57 UTF8 "uninstallReadBtn"
58 UTF8 "<init>"
59 UTF8 "()V"
60 UTF8 "Code"
61 UTF8 "LineNumberTable"
62 UTF8 "LocalVariableTable"
63 UTF8 "this"
64 UTF8 "Lcom/mrzhang/component/MainActivity;"
65 UTF8 "onCreate"
66 UTF8 "(Landroid/os/Bundle;)V"
67 UTF8 "savedInstanceState"
68 UTF8 "Landroid/os/Bundle;"
69 UTF8 "showFragment"
70 UTF8 "service"
71 UTF8 "Lcom/mrzhang/componentservice/readerbook/ReadBookService;"
72 UTF8 "router"
73 UTF8 "Lcom/mrzhang/component/componentlib/router/Router;"
74 UTF8 "StackMapTable"
75 Class #139
76 UTF8 "onResume"
77 UTF8 "asyncTask"
78 UTF8 "Landroid/os/AsyncTask;"
79 UTF8 "i"
80 UTF8 "I"
81 UTF8 "onClick"
82 UTF8 "(Landroid/view/View;)V"
83 UTF8 "v"
84 UTF8 "Landroid/view/View;"
85 UTF8 "SourceFile"
86 UTF8 "MainActivity.java"
87 NameAndType #58, type #59
88 NameAndType #65, type #66
89 Class #140
90 UTF8 "com/mrzhang/component/R$layout"
91 UTF8 "layout"
92 NameAndType #141, type #142
93 UTF8 "com/mrzhang/component/R$id"
94 UTF8 "id"
95 NameAndType #143, type #144
96 UTF8 "android/widget/Button"
97 NameAndType #55, type #56
98 NameAndType #57, type #56
99 NameAndType #145, type #146
100 UTF8 "com/mrzhang/component/MainActivity$1"
101 NameAndType #58, type #147
102 NameAndType #69, type #59
103 NameAndType #51, type #52
104 NameAndType #148, type #149
105 Class #150
106 NameAndType #151, type #152
107 NameAndType #53, type #54
108 Class #153
109 NameAndType #154, type #155
110 NameAndType #156, type #157
111 Class #139
112 NameAndType #158, type #159
113 UTF8 "com/mrzhang/componentservice/readerbook/ReadBookService"
114 Class #160
115 NameAndType #161, type #162
116 NameAndType #163, type #164
117 NameAndType #165, type #166
118 NameAndType #167, type #168
119 NameAndType #169, type #157
120 NameAndType #76, type #59
121 UTF8 "com/mrzhang/component/MainActivity$MyAsyncTask"
122 Class #170
123 NameAndType #171, type #172
124 UTF8 "java/lang/Object"
125 UTF8 "java/lang/StringBuilder"
126 UTF8 "smarking "
127 NameAndType #173, type #174
128 NameAndType #173, type #175
129 NameAndType #176, type #162
130 NameAndType #177, type #178
131 Class #179
132 NameAndType #180, type #157
133 UTF8 "com.mrzhang.share.applike.ShareApplike"
134 NameAndType #181, type #182
135 UTF8 "com/mrzhang/component/MainActivity"
136 UTF8 "android/support/v7/app/AppCompatActivity"
137 UTF8 "android/view/View$OnClickListener"
138 UTF8 "OnClickListener"
139 UTF8 "com/mrzhang/component/componentlib/router/Router"
140 UTF8 "com/mrzhang/component/R"
141 UTF8 "setContentView"
142 UTF8 "(I)V"
143 UTF8 "findViewById"
144 UTF8 "(I)Landroid/view/View;"
145 UTF8 "setOnClickListener"
146 UTF8 "(Landroid/view/View$OnClickListener;)V"
147 UTF8 "(Lcom/mrzhang/component/MainActivity;)V"
148 UTF8 "getSupportFragmentManager"
149 UTF8 "()Landroid/support/v4/app/FragmentManager;"
150 UTF8 "android/support/v4/app/FragmentManager"
151 UTF8 "beginTransaction"
152 UTF8 "()Landroid/support/v4/app/FragmentTransaction;"
153 UTF8 "android/support/v4/app/FragmentTransaction"
154 UTF8 "remove"
155 UTF8 "(Landroid/support/v4/app/Fragment;)Landroid/support/v4/app/FragmentTransaction;"
156 UTF8 "commit"
157 UTF8 "()I"
158 UTF8 "getInstance"
159 UTF8 "()Lcom/mrzhang/component/componentlib/router/Router;"
160 UTF8 "java/lang/Class"
161 UTF8 "getSimpleName"
162 UTF8 "()Ljava/lang/String;"
163 UTF8 "getService"
164 UTF8 "(Ljava/lang/String;)Ljava/lang/Object;"
165 UTF8 "getReadBookFragment"
166 UTF8 "()Landroid/support/v4/app/Fragment;"
167 UTF8 "add"
168 UTF8 "(ILandroid/support/v4/app/Fragment;)Landroid/support/v4/app/FragmentTransaction;"
169 UTF8 "commitAllowingStateLoss"
170 UTF8 "android/os/AsyncTask"
171 UTF8 "THREAD_POOL_EXECUTOR"
172 UTF8 "Ljava/util/concurrent/Executor;"
173 UTF8 "append"
174 UTF8 "(Ljava/lang/String;)Ljava/lang/StringBuilder;"
175 UTF8 "(I)Ljava/lang/StringBuilder;"
176 UTF8 "toString"
177 UTF8 "executeOnExecutor"
178 UTF8 "(Ljava/util/concurrent/Executor;[Ljava/lang/Object;)Landroid/os/AsyncTask;"
179 UTF8 "android/view/View"
180 UTF8 "getId"
181 UTF8 "registerComponent"
182 UTF8 "(Ljava/lang/String;)V"
ClassInfo{constPool=null, thisClass=46, accessFlags=33, superClass=47, interfaces=[48], thisClassName='com.mrzhang.component.MainActivity', major=51, minor=0}
ClassDog find target in /Users/Smarking/AndroidStudioProjects/newworld/DDComponentForAndroid/app/build/intermediates/classes/debug/com/mrzhang/component/MainActivity.class
java文件内容
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Fragment fragment;
FragmentTransaction ft;
Button installReadBookBtn;
Button uninstallReadBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
installReadBookBtn = (Button) findViewById(R.id.install_share);
uninstallReadBtn = (Button) findViewById(R.id.uninstall_share);
installReadBookBtn.setOnClickListener(this);
uninstallReadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Router.unregisterComponent("com.mrzhang.share.applike.ShareApplike");
}
});
showFragment();
}
private void showFragment() {
if (fragment != null) {
ft = getSupportFragmentManager().beginTransaction();
ft.remove(fragment).commit();
fragment = null;
}
Router router = Router.getInstance();
if (router.getService(ReadBookService.class.getSimpleName()) != null) {
ReadBookService service = (ReadBookService) router.getService(ReadBookService.class.getSimpleName());
fragment = service.getReadBookFragment();
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.tab_content, fragment).commitAllowingStateLoss();
}
}
@Override
protected void onResume() {
super.onResume();
for (int i = 0; i < 100; i++) {
AsyncTask asyncTask = new MyAsyncTask();
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "smarking " + i);
}
}
class MyAsyncTask extends AsyncTask<Object, String, String> {
@Override
protected String doInBackground(Object[] params) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return (String) params[0];
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d("zxx", s);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.install_share:
Router.registerComponent("com.ShareApplike");
break;
}
}
}
网友评论