`
jameswxx
  • 浏览: 779636 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java动态代理随笔一

    博客分类:
  • java
阅读更多

       先说一下java class的加载机制和与class文件的关系:Java 程序的工作机制: Java 对象都以单独的 class 文件存在, java 虚拟机将其载入并执行其虚拟机指令。

 

  class 的加载与实例化

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 虚拟机都在其启动时产生一个唯一的 class heap ,并把所有的 class instance 都分配在其中。其中每个类实例的信息又分两部分, fields 域和 methods 域。每个类实例各自拥有 fields ,但同一个类的不同实例共享 methods

 


java 反射的处理

简单例子代码:

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 和传入参数时,由虚拟机注入。

 

 

 

动态代理

一个简单例子代码:

研究 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());

        }

    }

} 
 
分享到:
评论

相关推荐

    Java的动态代理机制详解

    而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理是java的动态代理机制,所以本篇随笔是对java的动态机制进行一个回顾。...

    深入Java虚拟机第二版清晰版(带书签)

    7. **反射与动态代理**:Java的反射机制允许在运行时检查和修改程序行为,动态代理则提供了创建动态类型和接口实现的能力,这些在框架和库的开发中非常常见。 8. **安全机制**:JVM也扮演着安全管理的角色,书中...

    Java驴友社交系统.zip

    Java驴友社交系统是一个专为户外旅行爱好者设计的社交平台,它通过Java技术栈实现,提供了客户端和服务端的完整源码,便于学习和研究。在这个系统中,开发者可以深入理解如何构建一个完整的社交网络应用,涉及到的...

    优秀系统设计样例47-休闲娱乐代理售票系统(SpringBoot,源码、文档、lunwen、PPT).zip

    所以把休闲娱乐代理售票管理与现在网络相结合,利用java技术建设休闲娱乐代理售票系统,实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管理发展,丰富休闲娱乐代理售票管理经验能起到不少的促进...

    notes:网站描述代码

    2. **Java脚本**(通常指的是JavaScript):是一种广泛使用的客户端脚本语言,主要用于网页交互、动态内容生成和Web应用开发。 3. **Git**:是一种分布式版本控制系统,用于追踪对文件的修改,便于多人协作开发和...

    单点登录源码

    - 一站式支付解决方案,统一下单接口,支持支付宝、微信、网银等多种支付方式。不涉及业务的纯粹的支付平台。 - 统一下单(统一下单接口、统一扫码)、订单管理、数据分析、财务报表、商户管理、渠道管理、对账系统...

    SpringMvc依赖完整jar

    Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,主要用于构建 MVC(Model-View-Controller)模式的 Web 应用程序。在使用 Spring MVC 进行开发时,需要引入一系列的依赖 JAR 包来...

Global site tag (gtag.js) - Google Analytics