Java 程序的工作机制: Java 对象都以单独的 class 文件存在, java 虚拟机将其载入并执行其虚拟机指令。
Java 虚拟机查找这些 java 对象:
java 虚拟机根据 class path 来查找 java 对象,而虚拟机的 class path 又分为三层:
bootstrap : sun.boot.class.path
extension: java.ext.dirs
application: java.class.path
三个 class path 各有对应的 classloader 。由上而下形成父子关系
当程序中调用 new 指令,或者 ClassLoader.load 方法时。其顺序如下:
1. 首先查看 application 的 classloader 中是否已有对应的 class 缓存,如果有则返回,并根据 class 分配内存。如果没有,接下一步。
2. 首先查看 extension 的 classloader 中是否已有对应的 class 缓存,如果有则返回,并根据 class 分配内存。如果没有,接下一步。
3. 首先查看 bootstrap 的 classloader 中是否已有对应的 class 缓存,如果有则返回,并根据 class 分配内存。如果没有,接下一步。
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 虚拟机加载这些 java 对象:
每个 java 虚拟机都在其启动时产生一个唯一的 class heap ,并把所有的 class instance 都分配在其中。其中每个类实例的信息又分两部分, fields 域和 methods 域。每个类实例各自拥有 fields ,但同一个类的不同实例共享 methods
反射
JVM 对反射的处理
简单例子代码:
1import java.lang.reflect.InvocationHandler;
2
3import java.lang.reflect.Method;
4
5import java.lang.reflect.InvocationTargetException;
6
7import java.io.IOException;
8
9
10
11public 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
复杂例子代码:
1import java.lang.reflect.InvocationHandler;
2
3import java.lang.reflect.Method;
4
5import java.lang.reflect.InvocationTargetException;
6
7import java.io.IOException;
8
9
10
11public 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 虚拟机把每个 methods 当作一个执行单元。该执行单元带有两种签名:类签名和属性签名( public , static 等)。 反射的第一步,验证签名的合法性。验证通过后,顺序执行该 method 中的指令,当需要访问类实例的 fields 和传入参数时,由虚拟机注入。
动态代理
Sun 对动态代理的说明:
一个简单例子代码:
动态代理的内部实现——代码生成:
研究 JDK 源代码,发现在 Proxy 的 sun 实现中调用了 sun.misc.ProxyGenerator 类的 generateProxyClass( proxyName, interfaces) 方法,其返回值为 byte[] 和 class 文件的内存类型一致。于是做如下试验:
1public 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
运行该类,到 class 文件夹下,利用反编译技术,发现原来其采用了代码生产技术:
1public interface Temp{
2
3 public void Talk();
4
5 public void Run();
6
7}
8
9import java.lang.reflect.*;
10
11
12
13public 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.blogjava.net/AndersLin/archive/2006/06/11/51997.html