- 浏览: 776504 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
Fanatic357:
同问,请问这个 曲线 是用什么工具 监测得到的?
RocketMQ性能压测分析 -
sunshine_love:
8核 16G, 单master TPS 4w+,2m-2s- ...
RocketMQ性能压测分析 -
assertmyself:
很好,,获益良多!
jstack和线程dump分析 -
zhaoxiaoxiao:
非常赞,帮助理解了问题。今天也是遇到了这样的问题
hessian序列化bug -
wjg_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()); } } } |
发表评论
-
dubbo问题总结
2012-03-14 10:00 2983任何诡异的现象必然能找到问题原因,程序是不会骗人的 ... -
memcached客户端源码分析
2011-09-08 17:28 19950memcached的java客户端有好 ... -
说说单例模式
2011-05-23 11:12 3334单例模式?多么简单!也许吧,可是要通过简单的现象, ... -
jstack和线程dump分析
2011-05-12 13:48 180162一:jstack jstack命令的语法格式: js ... -
说说new Integer和Integer.valueOf
2010-11-11 15:04 6595看看这两个语句 Integer a=new Integ ... -
线程安全总结(二)
2010-11-11 12:36 5609关于线程安全总结(-)请看 http://www.iteye ... -
java线程安全总结
2010-11-09 20:48 15639最近想将java基 ... -
hadoop架构
2010-09-07 19:41 2684该文章我转自IBM开发者社区 ... -
HashMap深入分析
2010-09-03 19:36 5830java.util.HashMap是很常见的 ... -
CountDownLatch
2010-09-02 20:03 2964java的并发包真 ... -
ThreadPoolExecutor相关类的分析
2010-09-02 19:27 4597一:ThreadPoolExecutor ... -
随便说说
2010-09-01 19:29 2100这两天给系统 ... -
一波三折的rmi调用
2010-08-18 18:02 9854很久以前写了基于rmi的分布式java程序,现 ... -
java内存查看与分析
2010-08-07 17:03 22482业界有很多强 ... -
java动态代理之cglib
2010-06-22 17:27 2794cglib是一个 ... -
java动态代理随笔二
2010-06-22 16:29 1879jdk的动态代 ... -
关于hashcode和equals
2010-04-19 14:58 3389前几天有个同事问我,String a=" ... -
建设银行对接(五)
2010-02-09 17:34 2559public static void testVerify ... -
建设银行对接(四)
2010-02-09 17:32 3091上接“建设银行对接(三)”,javaeye的文章字数限制也太少 ... -
建设银行对接(三)
2010-02-09 17:24 3474前面两章请见我的博客 对建行返回的数据进行数字签名 ...
相关推荐
"Java完整随笔(学习)"可能包含了一系列关于Java编程的基础到高级概念的笔记,是学习Java的好资源。以下是一些可能涵盖的重要知识点: 1. **Java基础**:这部分可能包括了Java的基本语法,如变量、数据类型、...
而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理是java的动态代理机制,所以本篇随笔是对java的动态机制进行一个回顾。...
Java 记录随笔 Java 记录随笔是关于 Java 软件架构设计的笔记,涵盖了软件架构的基本原则、当前流行的技术、数据库存储结构、Web 界面用户接口层、业务层架构、持久层技术、XML 结构化信息传输和存储的重要性等多个...
1. 如何加断点:选择要设置的代码行,在行号的区域后面单击鼠标左键即可。 2. 如何运行加了断点的程序:在代码区域右键 Debug 执行。 3. 看哪里:看 Debugger 窗口,看 console 窗口(程序执行过程中的结果显示)。 ...
Java中的数组是一种基础且重要的数据结构,用于存储同种数据类型的多个值。数组提供了一种高效的方式来管理和操作一组数据,可以是整数、浮点数、字符或自定义对象。在Java中,数组的定义有两种格式: 1. `数据类型...
【Java - 框架 - Knife4j】随笔 在Java Web开发中,文档的生成与维护是一项重要但繁琐的工作。Knife4j,作为一款专门为Java RESTful API设计的文档增强工具,它极大地简化了这个过程,为开发者带来了诸多便利。本篇...
之前上传了JAVA笔记1 那么这次是JAVA笔记2 衔接上一次的
Java中的方法是编程中至关重要的概念,它封装了一段可重复使用的代码,使得程序更加模块化,提高了代码的复用性和可读性。方法的定义和调用是编写Java程序的基础。 方法的定义通常包括访问修饰符(如public)、静态...
本项目是一款基于Java和跨平台技术的crostitch涂鸦随笔设计与实现源码,包含65个文件,其中包括30个Java源文件、16个PNG图片文件、7个JavaScript文件、2个XML文件、1个Git忽略文件、1个Markdown文件、1个Maven项目...
每四位二进制数对应一个十进制数,如二进制的1101代表十进制的13,因为1*8 + 1*4 + 0*2 + 1*1 = 8 + 4 + 0 + 1 = 13。8421码在某些特定的数字处理场景中很有用,如电子表格软件或计算器。 Java中的位运算,如与(&)...
java课堂随笔,我这还有很多,有需要的话可以联系我,我会为大家提供很多的资料
JavaThings - Java安全漫谈笔记相关《Java安全漫谈》是我在写的一点Java学习相关的随笔,不是很严谨,也不是啥高。这个存储库主要是记录并整理一下,附加一些代码。Java 安全漫谈目录Java安全漫谈 - 01.Java的动态...
一年级数学第一学期教学随笔.pdf
IntelliJ IDEA,简称IDEA,是一款广受好评的Java集成开发环境,由JetBrains公司开发。它以其高效、智能的编码辅助和丰富的功能集,成为许多开发者首选的Java编程工具。IDEA不仅支持Java,还支持其他多种编程语言如...
在本文中,我们将深入探讨如何在Ubuntu操作系统上搭建一个完整的Java项目运行环境,包括安装Java Development Kit (JDK) 1.8、MySQL 5.7数据库服务以及Apache Tomcat 9应用服务器。这个过程对于任何希望在Linux环境...
关于小学一年级数学下册教学随笔.docx
6. **JSONP(JSON with Padding)**:适用于同源策略限制的场景,Java服务器端返回一个回调函数调用,JS通过动态插入`<script>`标签来执行这个回调。 具体到给定的文件中,"des.html"可能是一个关于数据解密的HTML...
这篇教学随笔主要探讨了以下几个方面: 首先,教师需要认识到一年级学生的特点,他们活泼好动,注意力维持时间较短。因此,创设有趣、富有吸引力的教学情境至关重要。例如,通过设立小奖励,如小红旗、小红花等,...
SpringSecurity是Java领域中一款强大的安全框架,主要用于Web应用程序的安全管理,包括认证和授权。它提供了全面的安全控制,从简单的密码编码到复杂的访问控制策略,为开发者提供了丰富的功能。本随笔将深入探讨...
苏教版一年级数学教学随笔.docx