Java 程序的工作機(jī)制: Java 對象都以單獨(dú)的 class 文件存在, java 虛擬機(jī)將其載入并執(zhí)行其虛擬機(jī)指令。
Java 虛擬機(jī)查找這些 java 對象:
java 虛擬機(jī)根據(jù) class path 來查找 java 對象,而虛擬機(jī)的 class path 又分為三層:
bootstrap : sun.boot.class.path
extension: java.ext.dirs
application: java.class.path
三個(gè) class path 各有對應(yīng)的 classloader 。由上而下形成父子關(guān)系
當(dāng)程序中調(diào)用 new 指令,或者 ClassLoader.load 方法時(shí)。其順序如下:
1. 首先查看 application 的 classloader 中是否已有對應(yīng)的 class 緩存,如果有則返回,并根據(jù) class 分配內(nèi)存。如果沒有,接下一步。
2. 首先查看 extension 的 classloader 中是否已有對應(yīng)的 class 緩存,如果有則返回,并根據(jù) class 分配內(nèi)存。如果沒有,接下一步。
3. 首先查看 bootstrap 的 classloader 中是否已有對應(yīng)的 class 緩存,如果有則返回,并根據(jù) class 分配內(nèi)存。如果沒有,接下一步。
4. 由 bootstrap 的 classloader 在其 class path 中試圖加載該 class ,如果有,則將該 class 放入 cache 中,并返回。如果沒有,接下一步。
5. 由 extension 的 classloader 在其 class path 中試圖加載該 class ,如果有,則將該 class 放入 cache 中,并返回。如果沒有,接下一步。
6. 由 application 的 classloader 在其 class path 中試圖加載該 class ,如果有,則將該 class 放入 cache 中,并返回。如果沒有,則拋出 ClassNotFound 的 exception 。
Java 虛擬機(jī)加載這些 java 對象:
每個(gè) java 虛擬機(jī)都在其啟動(dòng)時(shí)產(chǎn)生一個(gè)唯一的 class heap ,并把所有的 class instance 都分配在其中。其中每個(gè)類實(shí)例的信息又分兩部分, fields 域和 methods 域。每個(gè)類實(shí)例各自擁有 fields ,但同一個(gè)類的不同實(shí)例共享 methods
反射
JVM 對反射的處理
簡單例子代碼:
1
import java.lang.reflect.InvocationHandler;
2
3
import java.lang.reflect.Method;
4
5
import java.lang.reflect.InvocationTargetException;
6
7
import java.io.IOException;
8
9
10
11
public class Main
{
12
13
public static void main(String[] args)
{
14
15
TempImpl t1 = new TempImpl("temp1");
16
17
try
{
18
19
Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ;
20
21
t1Talk.invoke(t1, null);
22
23
} catch (NoSuchMethodException e)
{
24
25
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
26
27
} catch (IllegalAccessException e)
{
28
29
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
30
31
} catch (InvocationTargetException e)
{
32
33
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
34
35
}
36
37
try
{
38
39
System.in.read();
40
41
} catch (IOException e)
{
42
43
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
44
45
}
46
47
}
48
49
}
50
51
復(fù)雜例子代碼:
1
import java.lang.reflect.InvocationHandler;
2
3
import java.lang.reflect.Method;
4
5
import java.lang.reflect.InvocationTargetException;
6
7
import java.io.IOException;
8
9
10
11
public class Main
{
12
13
public static void main(String[] args)
{
14
15
TempImpl t1 = new TempImpl("temp1");
16
17
TempImpl t2 = new TempImpl("temp2");
18
19
Temp2 temp2 = new Temp2();
20
21
try
{
22
23
Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ;
24
25
Method t2Talk = t2.getClass().getMethod("Talk", new Class[0]) ;
26
27
t1Talk.invoke(t2, null);
28
29
t2Talk.invoke(t1, null);
30
31
if(t1Talk.equals(t2Talk))
{
32
33
System.out.println("equals");
34
35
}
36
37
else
{
38
39
System.out.println("not equals");
40
41
}
42
43
if(t1Talk==t2Talk)
{
44
45
System.out.println("ref equals");
46
47
}
48
49
else
{
50
51
System.out.println("ref not equals");
52
53
}
54
55
t2Talk.invoke(temp2, null);
56
57
} catch (NoSuchMethodException e)
{
58
59
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
60
61
} catch (IllegalAccessException e)
{
62
63
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
64
65
} catch (InvocationTargetException e)
{
66
67
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
68
69
}
70
71
try
{
72
73
System.in.read();
74
75
} catch (IOException e)
{
76
77
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
78
79
}
80
81
}
82
83
}
84
85
分析: java 虛擬機(jī)把每個(gè) methods 當(dāng)作一個(gè)執(zhí)行單元。該執(zhí)行單元帶有兩種簽名:類簽名和屬性簽名( public , static 等)。 反射的第一步,驗(yàn)證簽名的合法性。驗(yàn)證通過后,順序執(zhí)行該 method 中的指令,當(dāng)需要訪問類實(shí)例的 fields 和傳入?yún)?shù)時(shí),由虛擬機(jī)注入。
動(dòng)態(tài)代理
Sun 對動(dòng)態(tài)代理的說明:
一個(gè)簡單例子代碼:
動(dòng)態(tài)代理的內(nèi)部實(shí)現(xiàn)——代碼生成:
研究 JDK 源代碼,發(fā)現(xiàn)在 Proxy 的 sun 實(shí)現(xiàn)中調(diào)用了 sun.misc.ProxyGenerator 類的 generateProxyClass( proxyName, interfaces) 方法,其返回值為 byte[] 和 class 文件的內(nèi)存類型一致。于是做如下試驗(yàn):
1
public class ProxyClassFile
{
2
3
public static void main(String[] args)
{
4
5
String proxyName = "TempProxy";
6
7
TempImpl t = new TempImpl("proxy");
8
9
Class[] interfaces =t.getClass().getInterfaces();
10
11
12
13
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
14
15
proxyName, interfaces);
16
17
File f = new File("classes/TempProxy.class");
18
19
try
{
20
21
FileOutputStream fos = new FileOutputStream(f);
22
23
fos.write(proxyClassFile);
24
25
fos.flush();
26
27
fos.close();
28
29
} catch (FileNotFoundException e)
{
30
31
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
32
33
} catch (IOException e)
{
34
35
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
36
37
}
38
39
}
40
}
41
42
運(yùn)行該類,到 class 文件夾下,利用反編譯技術(shù),發(fā)現(xiàn)原來其采用了代碼生產(chǎn)技術(shù):
1
public interface Temp
{
2
3
public void Talk();
4
5
public void Run();
6
7
}
8
9
import java.lang.reflect.*;
10
11
12
13
public final class TempProxy extends Proxy
14
15
implements Temp
{
16
17
18
19
private static Method m4;
20
21
private static Method m2;
22
23
private static Method m0;
24
25
private static Method m3;
26
27
private static Method m1;
28
29
30
31
public TempProxy(InvocationHandler invocationhandler)
{
32
33
super(invocationhandler);
34
35
}
36
37
38
39
public final void Run()
{
40
41
try
{
42
43
h.invoke(this, m4, null);
44
45
return;
46
47
}
48
49
catch(Error _ex)
{ }
50
51
catch(Throwable throwable)
{
52
53
throw new UndeclaredThrowableException(throwable);
54
55
}
56
57
}
58
59
60
61
public final String toString()
{
62
63
try
{
64
65
return (String)h.invoke(this, m2, null);
66
67
}
68
69
catch(Error _ex)
{ }
70
71
catch(Throwable throwable)
{
72
73
throw new UndeclaredThrowableException(throwable);
74
75
}
76
77
return "";
78
79
}
80
81
82
83
public final int hashCode()
{
84
85
try
{
86
87
return ((Integer)h.invoke(this, m0, null)).intValue();
88
89
}
90
91
catch(Error _ex)
{ }
92
93
catch(Throwable throwable)
{
94
95
throw new UndeclaredThrowableException(throwable);
96
97
}
98
99
return 123;
100
101
}
102
103
104
105
public final void Talk()
{
106
107
try
{
108
109
h.invoke(this, m3, null);
110
111
return;
112
113
}
114
115
catch(Error _ex)
{ }
116
117
catch(Throwable throwable)
{
118
119
throw new UndeclaredThrowableException(throwable);
120
121
}
122
123
}
124
125
126
127
public final boolean equals(Object obj)
{
128
129
try
{
130
131
return ((Boolean)h.invoke(this, m1, new Object[]
{
132
133
obj
134
135
})).booleanValue();
136
137
}
138
139
catch(Error _ex)
{ }
140
141
catch(Throwable throwable)
{
142
143
throw new UndeclaredThrowableException(throwable);
144
145
}
146
147
return false;
148
149
}
150
151
152
153
static
{
154
155
try
{
156
157
m4 = Class.forName("Temp").getMethod("Run", new Class[0]);
158
159
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
160
161
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
162
163
m3 = Class.forName("Temp").getMethod("Talk", new Class[0]);
164
165
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]
{
166
167
Class.forName("java.lang.Object")
168
169
});
170
171
}
172
173
catch(NoSuchMethodException nosuchmethodexception)
{
174
175
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
176
177
}
178
179
catch(ClassNotFoundException classnotfoundexception)
{
180
181
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
182
183
}
184
185
}
186
187
}
188
189
本文地址:
http://www.tkk7.com/AndersLin/archive/2006/06/11/51997.html