`
jameswxx
  • 浏览: 776504 次
  • 性别: 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完整随笔(学习)

    "Java完整随笔(学习)"可能包含了一系列关于Java编程的基础到高级概念的笔记,是学习Java的好资源。以下是一些可能涵盖的重要知识点: 1. **Java基础**:这部分可能包括了Java的基本语法,如变量、数据类型、...

    Java的动态代理机制详解

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

    java记录随笔

    Java 记录随笔 Java 记录随笔是关于 Java 软件架构设计的笔记,涵盖了软件架构的基本原则、当前流行的技术、数据库存储结构、Web 界面用户接口层、业务层架构、持久层技术、XML 结构化信息传输和存储的重要性等多个...

    Java学习随笔6(Debug).docx

    1. 如何加断点:选择要设置的代码行,在行号的区域后面单击鼠标左键即可。 2. 如何运行加了断点的程序:在代码区域右键 Debug 执行。 3. 看哪里:看 Debugger 窗口,看 console 窗口(程序执行过程中的结果显示)。 ...

    Java学习随笔4(数组)

    Java中的数组是一种基础且重要的数据结构,用于存储同种数据类型的多个值。数组提供了一种高效的方式来管理和操作一组数据,可以是整数、浮点数、字符或自定义对象。在Java中,数组的定义有两种格式: 1. `数据类型...

    【Java - 框架 - Knife4j】随笔

    【Java - 框架 - Knife4j】随笔 在Java Web开发中,文档的生成与维护是一项重要但繁琐的工作。Knife4j,作为一款专门为Java RESTful API设计的文档增强工具,它极大地简化了这个过程,为开发者带来了诸多便利。本篇...

    JAVA笔记随笔

    之前上传了JAVA笔记1 那么这次是JAVA笔记2 衔接上一次的

    Java学习随笔5(方法)

    Java中的方法是编程中至关重要的概念,它封装了一段可重复使用的代码,使得程序更加模块化,提高了代码的复用性和可读性。方法的定义和调用是编写Java程序的基础。 方法的定义通常包括访问修饰符(如public)、静态...

    基于Java与跨平台技术的crostitch涂鸦随笔设计与实现源码

    本项目是一款基于Java和跨平台技术的crostitch涂鸦随笔设计与实现源码,包含65个文件,其中包括30个Java源文件、16个PNG图片文件、7个JavaScript文件、2个XML文件、1个Git忽略文件、1个Markdown文件、1个Maven项目...

    Java学习随笔7(进制).docx

    每四位二进制数对应一个十进制数,如二进制的1101代表十进制的13,因为1*8 + 1*4 + 0*2 + 1*1 = 8 + 4 + 0 + 1 = 13。8421码在某些特定的数字处理场景中很有用,如电子表格软件或计算器。 Java中的位运算,如与(&)...

    java课堂随笔

    java课堂随笔,我这还有很多,有需要的话可以联系我,我会为大家提供很多的资料

    分享Java相关的东西 - Java安全漫谈笔记相关内容.zip

    JavaThings - Java安全漫谈笔记相关《Java安全漫谈》是我在写的一点Java学习相关的随笔,不是很严谨,也不是啥高。这个存储库主要是记录并整理一下,附加一些代码。Java 安全漫谈目录Java安全漫谈 - 01.Java的动态...

    一年级数学第一学期教学随笔.pdf

    一年级数学第一学期教学随笔.pdf

    Java学习随笔3(IDEA的概述和功能).docx

    IntelliJ IDEA,简称IDEA,是一款广受好评的Java集成开发环境,由JetBrains公司开发。它以其高效、智能的编码辅助和丰富的功能集,成为许多开发者首选的Java编程工具。IDEA不仅支持Java,还支持其他多种编程语言如...

    ubuntu搭建Java项目运行环境-随笔记录.rar

    在本文中,我们将深入探讨如何在Ubuntu操作系统上搭建一个完整的Java项目运行环境,包括安装Java Development Kit (JDK) 1.8、MySQL 5.7数据库服务以及Apache Tomcat 9应用服务器。这个过程对于任何希望在Linux环境...

    关于小学一年级数学下册教学随笔.docx

    关于小学一年级数学下册教学随笔.docx

    Java代码调用HTML5中的JS函数算法

    6. **JSONP(JSON with Padding)**:适用于同源策略限制的场景,Java服务器端返回一个回调函数调用,JS通过动态插入`<script>`标签来执行这个回调。 具体到给定的文件中,"des.html"可能是一个关于数据解密的HTML...

    一年级语文教学随笔.pdf

    这篇教学随笔主要探讨了以下几个方面: 首先,教师需要认识到一年级学生的特点,他们活泼好动,注意力维持时间较短。因此,创设有趣、富有吸引力的教学情境至关重要。例如,通过设立小奖励,如小红旗、小红花等,...

    【Java-框架-SpringSecurity】单点登录(认证和授权)- 随笔

    SpringSecurity是Java领域中一款强大的安全框架,主要用于Web应用程序的安全管理,包括认证和授权。它提供了全面的安全控制,从简单的密码编码到复杂的访问控制策略,为开发者提供了丰富的功能。本随笔将深入探讨...

    苏教版一年级数学教学随笔.docx

    苏教版一年级数学教学随笔.docx

Global site tag (gtag.js) - Google Analytics