javavm,反射与动态代理
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对反射的处理
简单例子代码:
import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.invocationtargetexception;
import java.io.ioexception;
public class main {
public static void main(string[] args){
tempimpl t1 = new tempimpl("temp1");
try {
method t1talk = t1.getclass().getmethod("talk", new class[0]) ;
t1talk.invoke(t1, null);
} catch (nosuchmethodexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
} catch (illegalaccessexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
} catch (invocationtargetexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
}
try {
system.in.read();
} catch (ioexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
}
}
}
复杂例子代码:
import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
import java.lang.reflect.invocationtargetexception;
import java.io.ioexception;
public class main {
public static void main(string[] args){
tempimpl t1 = new tempimpl("temp1");
tempimpl t2 = new tempimpl("temp2");
temp2 temp2 = new temp2();
try {
method t1talk = t1.getclass().getmethod("talk", new class[0]) ;
method t2talk = t2.getclass().getmethod("talk", new class[0]) ;
t1talk.invoke(t2, null);
t2talk.invoke(t1, null);
if(t1talk.equals(t2talk)){
system.out.println("equals");
}
else{
system.out.println("not equals");
}
if(t1talk==t2talk){
system.out.println("ref equals");
}
else{
system.out.println("ref not equals");
}
t2talk.invoke(temp2, null);
} catch (nosuchmethodexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
} catch (illegalaccessexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
} catch (invocationtargetexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
}
try {
system.in.read();
} catch (ioexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
}
}
}
分析:java虚拟机把每个methods当作一个执行单元。该执行单元带有两种签名:类签名和属性签名(public,static等)。 反射的第一步,验证签名的合法性。验证通过后,顺序执行该method中的指令,当需要访问类实例的fields和传入参数时,由虚拟机注入。
动态代理
sun对动态代理的说明:
一个简单例子代码:
动态代理的内部实现――代码生成:
研究jdk源代码,发现在proxy的sun实现中调用了sun.misc.proxygenerator类的generateproxyclass( proxyname, interfaces)方法,其返回值为byte[]和class文件的内存类型一致。于是做如下试验:
public class proxyclassfile{
public static void main(string[] args){
string proxyname = "tempproxy";
tempimpl t = new tempimpl("proxy");
class[] interfaces =t.getclass().getinterfaces();
byte[] proxyclassfile = proxygenerator.generateproxyclass(
proxyname, interfaces);
file f = new file("classes/tempproxy.class");
try {
fileoutputstream fos = new fileoutputstream(f);
fos.write(proxyclassfile);
fos.flush();
fos.close();
} catch (filenotfoundexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
} catch (ioexception e) {
e.printstacktrace(); //to change body of catch statement use file | settings | file templates.
}
}
}
运行该类,到class文件夹下,利用反编译技术,发现原来其采用了代码生产技术:
public interface temp{
public void talk();
public void run();
}
import java.lang.reflect.*;
public final class tempproxy extends proxy
implements temp{
private static method m4;
private static method m2;
private static method m0;
private static method m3;
private static method m1;
public tempproxy(invocationhandler invocationhandler) {
super(invocationhandler);
}
public final void run() {
闽公网安备 35060202000074号