(从csdn的blog转来)
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());
}
}
}
分享到:
相关推荐
Java程序的工作机制:Java对象都以单独的class文件存在,java虚拟机将其载入并执行其虚拟机指令。
reflection是一系列的API,用于表示或者处理当前JVM中的类,接口和对象. java.lang.reflect/java.lang.Class 在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
调用对象的方法,与直接在源代码中的交互是一样的,但又提供了额外的在运行时候的灵活性,但反射的一个最大的弊端就是性能比较差,相同的操作,用反射API所需的时间大概比直接使用慢一两个数量级,不过现在的JVM实现...
javaStrengthenJava 高级特性增强。包括多线程增强、Java并发包、Java JMS技术、Java JVM技术、Java动态代理以及反射。
简介一些Java程序使用反射通过动态加载和执行类来隐藏其代码。 您可以从内存中转储它们,但是如果它们在执行后立即被卸载怎么办? 您可以编辑rt.jar并将钩子放在各种反射方法上。 但是,如果程序直接使用本机类加载...
文章目录一、Java反射定义二、Java反射机制实现1、Class对象获取2、获取class对象的摘要信息3、获取class对象的属性、方法、构造函数等三、反射的应用场景1、动态代理2、自定义注解实现日志管理 写在前面:Java反射...
动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。 - **优点:** 运行期类型的判断,动态加载类,提高代码灵活度。 - **缺点:** 性能瓶颈:反射相当于一...
Proxy动态代理机制详解 从整体上观察对象 网络开发 Servlet基础,生命周期执行过程 Http请求详解,握手挥手流程简介 会话跟踪技术,Session和Cookie详解 过滤器、监听器、拦截器,应用详解 Servlet 集成 C3P0
1、掌握多线程 2、掌握并发包下的队列 3、了解JMS 4、掌握JVM技术 5、掌握反射和动态代理
它比使用java反射的JDK动态代理要快。 CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。 CGLIB缺点:对于...
java的高级特性总结,多线程的各种实现,jvm技术,以及动态代理和反射的理解
包括JavaSE基础(多态、异常处理、常用API、数据类型、IO操作、集合、多线程和并发库、内部类)、JavaSE高级(反射、动态代理、设计模式&回收机制、加载器、JVM基础、GC基础)、JavaWeb基础(JDBC技术、HTTP协议、...
本书是Java技术经典参考书,多年畅销不衰,第7版在保留以前版本风格的基础上,涵盖Java 2开发平台标准版J2SE 5.0的基础知识,主要内容包括面向对象程序设计、反射与代理、接口与内部类、事件监听器模型、使用Swing ...
Spring 4.x ...动态代理:在程序运行期间由JVM根据反射机制动态生成的,不存在代理类的字节码文件,代理对象和目标对象的关系是在程序运行时决定的。 动态代理两种方式 JDK代理:要求目标对象必须有接口
动态代理 JDK8新特性 集合容器 多线程与并发 Spring SpringMVC SpringBoot Mybatis 数据结构与算法 入门基础 基础数据结构 数组&链表 数组&链表进阶 栈 队列 算法思想 数论&枚举&递归&分治&回溯 排序及其源码实现 ...
ORM,动态SQL、动态代理 第十篇:Spring 那点破事!IOC、AOP、生命周期、动态代理、设计模式 第十一篇:Spring Boot !starter组件、JPA、定时任务、全局异常 第十二篇:Spring Cloud !Gateway、注册发现、Hystrix...
揭开springAOP神秘面纱(动态代理) Mysql性能优化之索引优化 写实现Tomcat服务器 移动后台端框架设计 公司级框架原理解析 解密公司内部框架开发(打造属于自己的专属框架) 手写Tomca之深度解析动态资源请求原理 深度...
反射机制;多线程;IO/NIO; 网络编程;常用数据结构和相关算法。 2、对面向对象的软件开发思想有清晰的认识、熟悉掌握常用的设计模式;设计模式;单例模式;工厂模式;代理模式;模板方法模式;责任链模式等。 3...
【对线面试官】Java反射 && 动态代理 爪哇 【对线面试官】多线程基础 【对线面试官】 CAS 【对线面试官】同步进行 【对线面试官】AQS&&ReentrantLock 【对线面试官】线程池 【对线面试官】ThreadLocal 【对线面试官...
1.3.2 Java程序的运行机制和JVM 6 1.4 开发Java的准备 7 1.4.1 安装JDK 8 学生提问:不是说JVM是运行Java程序的虚拟机吗?那JRE和JVM的关系是怎样的呢? 8 学生提问:为什么不安装公共JRE系统呢? 9 1.4.2 设置...