您的位置:首页 > 其它

深入研究jvm,动态代理

2010-02-24 10:13 225 查看
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()
{

try {

h.invoke(this, m4, null);

return;

}

catch(Error _ex) { }

catch(Throwable throwable)
{

throw new UndeclaredThrowableException(throwable);

}

}

public final String toString(){

try{

return (String)h.invoke(this, m2, null);

}

catch(Error _ex) { }

catch(Throwable throwable)
{

throw new UndeclaredThrowableException(throwable);

}

return "";

}

public final int hashCode() {

try {

return ((Integer)h.invoke(this, m0, null)).intValue();

}

catch(Error _ex) { }

catch(Throwable throwable){

throw new UndeclaredThrowableException(throwable);

}

return 123;

}

public final void Talk(){

try{

h.invoke(this, m3, null);

return;

}

catch(Error _ex) { }

catch(Throwable throwable) {

throw new UndeclaredThrowableException(throwable);

}

}

public final boolean equals(Object obj) {

try
{

return ((Boolean)h.invoke(this, m1, new Object[] {

obj

})).booleanValue();

}

catch(Error _ex) { }

catch(Throwable throwable) {

throw new UndeclaredThrowableException(throwable);

}

return false;

}

static{

try{

m4 = Class.forName("Temp").getMethod("Run", new Class[0]);

m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);

m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);

m3 = Class.forName("Temp").getMethod("Talk", new Class[0]);

m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {

Class.forName("java.lang.Object")

});

}

catch(NoSuchMethodException nosuchmethodexception) {

throw new NoSuchMethodError(nosuchmethodexception.getMessage());

}

catch(ClassNotFoundException classnotfoundexception) {

throw new NoClassDefFoundError(classnotfoundexception.getMessage());

}

}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: