- 浏览: 426088 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Glogo:
楼主您好,我在试验您的代码的时候发现新开的三个子线程并没有一直 ...
java 高并发 ReentrantLock -- 可重入的锁 -
univasity:
最近发觉也被限速了,投诉一下就好一会~~ 看来明天又要和电信M ...
ADSL上网速度慢 都是帐号限速惹的祸 -
liuyuanhui0301:
java 高并发 ReentrantLock -- 可重入的锁 -
dang_java:
呵.很好的说明文档.
JXTA技术与应用发展 -
helloqidi:
谢谢,学习了
SQL中exists和in的区别
一、Java ClassLoader
1,什么是ClassLoader
与 C 或 C++ 编写的程序不同,Java 程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件对应于一个 Java 类。
此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。ClassLoader 是 JVM 中将类装入内存的那部分。
而且,Java ClassLoader 就是用 Java 语言编写的。这意味着创建您自己的 ClassLoader 非常容易,不必了解 JVM 的微小细节。
2,一些重要的方法
A)loadClass
ClassLoader.loadClass() 是ClassLoader的入口点。该方法的定义为:Class loadClass( String name, boolean resolve );
name:JVM 需要的类的名称,如 Foo 或 java.lang.Object。
resolve:参数告诉方法是否需要解析类。
B)defineClass
defineClass方法是ClassLoader的主要诀窍。该方法接受由原始字节组成的数组并把它转换成Class对象。
C)findSystemClass
findSystemClass方法从本地文件系统中寻找类文件,如果存在,就使用defineClass将原始字节转换成Class对象,以将该文件转换成类。
D)resolveClass
可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的loadClass时可以调用resolveClass,这取决于loadClass的resolve参数的值。
E)findLoadedClass
findLoadedClass充当一个缓存:当请求loadClass装入类时,它调用该方法来查看ClassLoader是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。
3,Java2中ClassLoader的变动
1)loadClass的缺省实现
在Java2中loadClass的实现嵌入了大多数查找类的一般方法,并使您通过覆盖findClass方法来定制它,在适当的时候findClass会调用loadClass。
这种方式的好处是可能不一定要覆盖loadClass,只要覆盖findClass就行了,这减少了工作量。
2)新方法:findClass
loadClass的缺省实现调用这个新方法。
3)新方法:getSystemClassLoader
如果覆盖findClass或loadClass,getSystemClassLoader让我们以实际ClassLoader对象来访问系统ClassLoader,而不是固定的从findSystemClass 调用它。
4)新方法:getParent
为了将类请求委托给父ClassLoader,这个新方法允许ClassLoader获取它的父ClassLoader。
4,定制ClassLoader
其实我们或多或少都使用过定制的ClassLoader,因为Applet查看器中就包含一个定制的ClassLoader。
它不在本地文件系统中寻找类,而是访问远程服务器上的 Web 站点,经过 HTTP 装入原始的字节码文件,并把它们转换成JVM 内的类。
Applet查看器中的ClassLoader还可以做其它事情:它们支持安全性以及使不同的Applet在不同的页面上运行而互不干扰。
我们将写一个自己的ClassLoader实现示例,它将实现如下步骤,这也是ClassLoader的工作原理:
# 调用 findLoadedClass 来查看是否存在已装入的类。
# 如果没有,那么采用那种特殊的神奇方式来获取原始字节。
# 如果已有原始字节,调用defineClass将它们转换成Class对象。
# 如果没有原始字节,然后调用findSystemClass查看是否从本地文件系统获取类。
# 如果resolve参数是true,那么调用resolveClass解析Class对象。
# 如果还没有类,返回ClassNotFoundException。
# 否则,将类返回给调用程序。
话不多说,看看代码先:
FileClassLoader.java:
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- public class FileClassLoader extends ClassLoader {
- public Class findClass(String name) {
- byte[] data = loadClassData(name);
- return defineClass(name, data, 0, data.length);
- }
- private byte[] loadClassData(String name) {
- FileInputStream fis = null;
- byte[] data = null;
- try {
- fis = new FileInputStream(new File("D:\\project\\test\\" + name + ".class"));
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int ch = 0;
- while ((ch = fis.read()) != -1) {
- baos.write(ch);
- }
- data = baos.toByteArray();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return data;
- }
- }
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class FileClassLoader extends ClassLoader { public Class findClass(String name) { byte[] data = loadClassData(name); return defineClass(name, data, 0, data.length); } private byte[] loadClassData(String name) { FileInputStream fis = null; byte[] data = null; try { fis = new FileInputStream(new File("D:\\project\\test\\" + name + ".class")); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int ch = 0; while ((ch = fis.read()) != -1) { baos.write(ch); } data = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return data; } }
MyApp.java:
- public class MyApp {
- public static void main(String[] args) throws Exception {
- FileClassLoader loader = new FileClassLoader();
- Class objClass = loader.findClass("MyApp");
- Object obj = objClass.newInstance();
- System.out.println(objClass.getName());
- System.out.println(objClass.getClassLoader());
- System.out.println(obj);
- }
- }
public class MyApp { public static void main(String[] args) throws Exception { FileClassLoader loader = new FileClassLoader(); Class objClass = loader.findClass("MyApp"); Object obj = objClass.newInstance(); System.out.println(objClass.getName()); System.out.println(objClass.getClassLoader()); System.out.println(obj); } }
编译并运行MyApp类,结果为:
- MyApp
- FileClassLoader@757aef
- MyApp@9cab16
二、Bytecode
1,什么是Bytecode
C/C++编译器把源代码编译成汇编代码,Java编译器把Java源代码编译成字节码bytecode。
Java跨平台其实就是基于相同的bytecode规范做不同平台的虚拟机,我们的Java程序编译成bytecode后就可以在不同平台跑了。
.net框架有IL(intermediate language),汇编是C/C++程序的中间表达方式,而bytecode可以说是Java平台的中间语言。
了解Java字节码知识对debugging、performance tuning以及做一些高级语言扩展或框架很有帮助。
2,使用javap生成Bytecode
JDK自带的javap.exe文件可以反汇编Bytecode,让我们看个例子:
Test.java:
- public class Test {
- public static void main(String[] args) {
- int i = 10000;
- System.out.println("Hello Bytecode! Number = " + i);
- }
- }
public class Test { public static void main(String[] args) { int i = 10000; System.out.println("Hello Bytecode! Number = " + i); } }
编译后的Test.class:
- 漱壕 1 +
- <init> ()V Code LineNumberTable main ([Ljava/lang/String;)V
- SourceFile Test.java
使用javap -c Test > Test.bytecode生成的Test.bytecode:
- Compiled from "Test.java"
- public class Test extends java.lang.Object{
- public Test();
- Code:
- 0: aload_0
- 1: invokespecial #1; //Method java/lang/Object."<init>":()V
- 4: return
- public static void main(java.lang.String[]);
- Code:
- 0: sipush 10000
- 3: istore_1
- 4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
- 7: new #3; //class java/lang/StringBuilder
- 10: dup
- 11: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
- 14: ldc #5; //String Hello Bytecode! Number =
- 16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
- 19: iload_1
- 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
- 23: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
- 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
- 29: return
- }
Compiled from "Test.java" public class Test extends java.lang.Object{ public Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: sipush 10000 3: istore_1 4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 7: new #3; //class java/lang/StringBuilder 10: dup 11: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 14: ldc #5; //String Hello Bytecode! Number = 16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: iload_1 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 23: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 29: return }
JVM就是一个基于stack的机器,每个thread拥有一个存储着一些frames的JVM stack,每次调用一个方法时生成一个frame。
一个frame包括一个local variables数组(本地变量表),一个Operand LIFO stack和运行时常量池的一个引用。
我们来简单分析一下生成的字节码指令:
aload和iload指令的“a”前缀和“i”分别表示对象引用和int类型,其他还有“b”表示byte,“c”表示char,“d”表示double等等
我们这里的aload_0表示将把local variable table中index 0的值push到Operand stack,iload_1类似
invokespecial表示初始化对象,return表示返回
sipush表示把10000这个int值push到Operand stack
getstatic表示取静态域
invokevirtual表示调用一些实例方法
这些指令又称为opcode,Java一直以来只有约202個Opcode,具体请参考Java Bytecode规范。
我们看到Test.class文件不全是二进制的指令,有些是我们可以识别的字符,这是因为有些包名、类名和常量字符串没有编译成二进制Bytecode指令。
3,体验字节码增强的魔力
我们J2EE常用的Hibernate、Spring都用到了动态字节码修改来改变类的行为。
让我们通过看看ASM的org.objectweb.asm.MethodWriter类的部分方法来理解ASM是如何修改字节码的:
- class MethodWriter implements MethodVisitor {
- private ByteVector code = new ByteVector();
- public void visitIntInsn(final int opcode, final int operand) {
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, operand, null, null);
- } else if (opcode != Opcodes.NEWARRAY) {
- // updates current and max stack sizes only for NEWARRAY
- // (stack size variation = 0 for BIPUSH or SIPUSH)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- if (opcode == Opcodes.SIPUSH) {
- code.put12(opcode, operand);
- } else { // BIPUSH or NEWARRAY
- code.put11(opcode, operand);
- }
- }
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- boolean itf = opcode == Opcodes.INVOKEINTERFACE;
- Item i = cw.newMethodItem(owner, name, desc, itf);
- int argSize = i.intVal;
- // Label currentBlock = this.currentBlock;
- if (currentBlock != null) {
- if (compute == FRAMES) {
- currentBlock.frame.execute(opcode, 0, cw, i);
- } else {
- /*
- * computes the stack size variation. In order not to recompute
- * several times this variation for the same Item, we use the
- * intVal field of this item to store this variation, once it
- * has been computed. More precisely this intVal field stores
- * the sizes of the arguments and of the return value
- * corresponding to desc.
- */
- if (argSize == 0) {
- // the above sizes have not been computed yet,
- // so we compute them...
- argSize = getArgumentsAndReturnSizes(desc);
- // ... and we save them in order
- // not to recompute them in the future
- i.intVal = argSize;
- }
- int size;
- if (opcode == Opcodes.INVOKESTATIC) {
- size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
- } else {
- size = stackSize - (argSize >> 2) + (argSize & 0x03);
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- }
- // adds the instruction to the bytecode of the method
- if (itf) {
- if (argSize == 0) {
- argSize = getArgumentsAndReturnSizes(desc);
- i.intVal = argSize;
- }
- code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
- } else {
- code.put12(opcode, i.index);
- }
- }
- }
class MethodWriter implements MethodVisitor { private ByteVector code = new ByteVector(); public void visitIntInsn(final int opcode, final int operand) { // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, operand, null, null); } else if (opcode != Opcodes.NEWARRAY) { // updates current and max stack sizes only for NEWARRAY // (stack size variation = 0 for BIPUSH or SIPUSH) int size = stackSize + 1; if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method if (opcode == Opcodes.SIPUSH) { code.put12(opcode, operand); } else { // BIPUSH or NEWARRAY code.put11(opcode, operand); } } public void visitMethodInsn( final int opcode, final String owner, final String name, final String desc) { boolean itf = opcode == Opcodes.INVOKEINTERFACE; Item i = cw.newMethodItem(owner, name, desc, itf); int argSize = i.intVal; // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, 0, cw, i); } else { /* * computes the stack size variation. In order not to recompute * several times this variation for the same Item, we use the * intVal field of this item to store this variation, once it * has been computed. More precisely this intVal field stores * the sizes of the arguments and of the return value * corresponding to desc. */ if (argSize == 0) { // the above sizes have not been computed yet, // so we compute them... argSize = getArgumentsAndReturnSizes(desc); // ... and we save them in order // not to recompute them in the future i.intVal = argSize; } int size; if (opcode == Opcodes.INVOKESTATIC) { size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; } else { size = stackSize - (argSize >> 2) + (argSize & 0x03); } // updates current and max stack sizes if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method if (itf) { if (argSize == 0) { argSize = getArgumentsAndReturnSizes(desc); i.intVal = argSize; } code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); } else { code.put12(opcode, i.index); } } }
通过注释我们可以大概理解visitIntInsn和visitMethodInsn方法的意思。
比如visitIntInsn先计算stack的size,然后根据opcode来判断是SIPUSH指令还是BIPUSH or NEWARRAY指令,并相应的调用字节码修改相关的方法。
三、ASM
我们知道Java是静态语言,而python、ruby是动态语言,Java程序一旦写好很难在运行时更改类的行为,而python、ruby可以。
不过基于bytecode层面上我们可以做一些手脚,来使Java程序多一些灵活性和Magic,ASM就是这样一个应用广泛的开源库。
ASM is a Java bytecode manipulation framework. It can be used to dynamically generate stub classes or other proxy classes,
directly in binary form, or to dynamically modify classes at load time, i.e., just before they are loaded into the Java
Virtual Machine.
ASM完成了BCEL和SERP同样的功能,但ASM
只有30多k,而后两者分别是350k和150k。apache真是越来越过气了。
让我们来看一个ASM的简单例子Helloworld.java,它生成一个Example类和一个main方法,main方法打印"Hello world!"语句:
- import java.io.FileOutputStream;
- import java.io.PrintStream;
- import org.objectweb.asm.ClassWriter;
- import org.objectweb.asm.MethodVisitor;
- import org.objectweb.asm.Opcodes;
- import org.objectweb.asm.Type;
- import org.objectweb.asm.commons.GeneratorAdapter;
- import org.objectweb.asm.commons.Method;
- public class Helloworld extends ClassLoader implements Opcodes {
- public static void main(final String args[]) throws Exception {
- // creates a ClassWriter for the Example public class,
- // which inherits from Object
- ClassWriter cw = new ClassWriter(0);
- cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
- MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
- null);
- mw.visitVarInsn(ALOAD, 0);
- mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
- mw.visitInsn(RETURN);
- mw.visitMaxs(1, 1);
- mw.visitEnd();
- mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
- "([Ljava/lang/String;)V", null, null);
- mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
- "Ljava/io/PrintStream;");
- mw.visitLdcInsn("Hello world!");
- mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
- "(Ljava/lang/String;)V");
- mw.visitInsn(RETURN);
- mw.visitMaxs(2, 2);
- mw.visitEnd();
- byte[] code = cw.toByteArray();
- FileOutputStream fos = new FileOutputStream("Example.class");
- fos.write(code);
- fos.close();
- Helloworld loader = new Helloworld();
- Class exampleClass = loader
- .defineClass("Example", code, 0, code.length);
- exampleClass.getMethods()[0].invoke(null, new Object[] { null });
- // ------------------------------------------------------------------------
- // Same example with a GeneratorAdapter (more convenient but slower)
- // ------------------------------------------------------------------------
- cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
- Method m = Method.getMethod("void <init> ()");
- GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null,
- cw);
- mg.loadThis();
- mg.invokeConstructor(Type.getType(Object.class), m);
- mg.returnValue();
- mg.endMethod();
- m = Method.getMethod("void main (String[])");
- mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
- mg.getStatic(Type.getType(System.class), "out", Type
- .getType(PrintStream.class));
- mg.push("Hello world!");
- mg.invokeVirtual(Type.getType(PrintStream.class), Method
- .getMethod("void println (String)"));
- mg.returnValue();
- mg.endMethod();
- cw.visitEnd();
- code = cw.toByteArray();
- loader = new Helloworld();
- exampleClass = loader.defineClass("Example", code, 0, code.length);
- exampleClass.getMethods()[0].invoke(null, new Object[] { null });
- }
- }
import java.io.FileOutputStream; import java.io.PrintStream; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; public class Helloworld extends ClassLoader implements Opcodes { public static void main(final String args[]) throws Exception { // creates a ClassWriter for the Example public class, // which inherits from Object ClassWriter cw = new ClassWriter(0); cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mw.visitVarInsn(ALOAD, 0); mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); mw.visitInsn(RETURN); mw.visitMaxs(1, 1); mw.visitEnd(); mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mw.visitLdcInsn("Hello world!"); mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); mw.visitInsn(RETURN); mw.visitMaxs(2, 2); mw.visitEnd(); byte[] code = cw.toByteArray(); FileOutputStream fos = new FileOutputStream("Example.class"); fos.write(code); fos.close(); Helloworld loader = new Helloworld(); Class exampleClass = loader .defineClass("Example", code, 0, code.length); exampleClass.getMethods()[0].invoke(null, new Object[] { null }); // ------------------------------------------------------------------------ // Same example with a GeneratorAdapter (more convenient but slower) // ------------------------------------------------------------------------ cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); Method m = Method.getMethod("void <init> ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); m = Method.getMethod("void main (String[])"); mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); mg.getStatic(Type.getType(System.class), "out", Type .getType(PrintStream.class)); mg.push("Hello world!"); mg.invokeVirtual(Type.getType(PrintStream.class), Method .getMethod("void println (String)")); mg.returnValue(); mg.endMethod(); cw.visitEnd(); code = cw.toByteArray(); loader = new Helloworld(); exampleClass = loader.defineClass("Example", code, 0, code.length); exampleClass.getMethods()[0].invoke(null, new Object[] { null }); } }
我们看到上面的例子分别使用ASM的MethodVisitor和GeneratorAdapter两种方式来动态生成Example类并调用打印语句。
四、cglib
cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime.
cglib是Code Generation Library的缩写。
cglib依赖于ASM库。
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制,Spring则是利用cglib来实现动态代理。
而JDK的动态代理机制要求有接口才行,这样就强制我们的pojo实现某个接口。
这里还是提供一个cglib的入门级的示例:
MyClass.java:
- public class MyClass {
- public void print() {
- System.out.println("I'm in MyClass.print!");
- }
- }
public class MyClass { public void print() { System.out.println("I'm in MyClass.print!"); } }
Main.java:
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class Main {
- public static void main(String[] args) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(MyClass.class);
- enhancer.setCallback(new MethodInterceptorImpl());
- MyClass my = (MyClass) enhancer.create();
- my.print();
- }
- private static class MethodInterceptorImpl implements MethodInterceptor {
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- // log something
- System.out.println(method + " intercepted!");
- proxy.invokeSuper(obj, args);
- return null;
- }
- }
- }
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyClass.class); enhancer.setCallback(new MethodInterceptorImpl()); MyClass my = (MyClass) enhancer.create(); my.print(); } private static class MethodInterceptorImpl implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // log something System.out.println(method + " intercepted!"); proxy.invokeSuper(obj, args); return null; } } }
发表评论
-
深入JVM锁机制
2011-09-19 01:00 969目前在Java中存在两种 ... -
java 正则表达式 非捕获组(特殊构造)Special Constructs(Non-Capturing)
2011-06-20 23:15 1638针对Java API文档中的正则表达式关于特殊构造(非捕获组) ... -
Java文件映射[mmap]揭秘
2011-06-08 20:10 1162前言 相信现在 ... -
原创 java的Mmap二三事
2011-06-08 19:46 1192转自 :http://blog.csdn.net/kabini ... -
java 安全沙箱模型详解
2011-04-18 16:29 933起到第一道安全保障作 ... -
非阻塞算法-ReentrantLock代码剖析之ReentrantLock.lock
2011-04-15 13:59 1076ReentrantLock是java.util.concurr ... -
CyclicBarrier与CountDownLatch、栅栏与计数器
2011-04-15 10:39 1457在多线程设计中,我猜常常会遇到线程间相互等待以及某个线程等待1 ... -
Java KeyStore
2011-04-13 17:17 1460简介Java自带的keytool工具是个密钥和证书管理工具。它 ... -
Security Managers and the JavaTM 2 SDK
2011-04-12 13:37 766The original Link : http://do ... -
Something about SecurityManager
2011-04-12 13:33 776The Java Security was made up o ... -
Using the Java SecurityManager with Tomcat
2011-04-12 13:30 990Why use a SecurityManager? The ... -
Java安全管理器(Security Manager)(
2011-04-11 14:54 878转载自: http://blog.sina.com.cn/s/ ... -
Java对象的强、软、弱和虚引用(1)
2011-04-01 08:44 793本文介绍Java对象的强 ... -
Java对象的强引用、软引用、弱引用和虚引用
2011-04-01 08:39 900在JDK1.2以前的版本中, ... -
java 高并发 ReentrantLock -- 可重入的锁
2011-03-30 08:09 2353ReentrantLock -- 可重入的锁 可重入锁指 ... -
线程运行栈信息的获取
2011-03-24 17:23 1301线程运行栈信息的获取 ... -
java序列化——Serializable
2011-03-15 23:17 1064类通过实现 java.io.Serializable 接口 ... -
Java aio(异步网络IO)初探
2011-03-11 16:34 1554按照《Unix网络编程》的 ... -
JAVA NIO 简介
2011-03-11 13:38 11101. 基本 概念 IO 是主存和外部设备 ( 硬盘、终 ... -
[字节码系列]ObjectWeb ASM构建Method Monitor
2011-03-08 18:08 890在前面的篇章中,我们看到Java Instru ...
相关推荐
理解ClassLoader的工作原理以及如何定制它,对于深入学习Java的运行机制和进行高级应用开发具有重要意义。本篇文章将深入探讨Java ClassLoader的内部工作,并通过一个具体的实例来展示如何定制自己的ClassLoader。 ...
深入Java 2 SDK.pdf`可能涉及的是Java与其他工具和技术的集成,如与微软Office的交互、使用Visual Studio .NET管理Java应用、Ant构建工具的使用以及对Java 2 SDK的深入理解,这些都可能间接地涉及到ClassLoader的...
Java ClassLoader机制是Java运行时环境中的核心组件之一,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先...
在本篇中,我们将详细探讨ClassLoader的工作原理、ASM库的使用以及如何利用这些工具进行动态字节码增强。 首先,我们来看Java的类加载机制。Java中的类加载主要由ClassLoader完成,它遵循“双亲委派模型”(Parents...
理解ClassLoader的工作原理对于深入学习Java以及进行JVM优化、插件开发等高级技术至关重要。下面将详细介绍Java ClassLoader的基本概念、工作流程、类加载机制以及自定义ClassLoader。 1. **ClassLoader基本概念** ...
### Java ClassLoader与ClassPath详解 #### 一、概述 在Java编程中,类加载机制是十分关键的一个环节。类加载器(`ClassLoader`)负责将编译后的`.class`文件加载到Java虚拟机(JVM)中执行,而类路径(`ClassPath...
破解java加密的ClassLoader.java,在classloader植入破解代码
### Java ClassLoader原理详解 #### 摘要 本文探讨了Java虚拟机(JVM)中的一个重要特性:动态类加载(Dynamic Class Loading)。...了解和掌握这些概念对于深入理解和高效利用Java平台至关重要。
Java ClassLoader机制是Java虚拟机(JVM)中一个至关重要的组成部分,它的主要任务是将类的.class文件加载到JVM中,使得程序能够运行。ClassLoader不仅负责类的加载,还涉及类的验证、初始化等一系列过程。理解...
为了更好地理解和利用Java的这一特性,本篇将详细介绍Java ClassLoader的作用及其工作原理,并通过构建一个示例ClassLoader来帮助读者深入理解如何自定义ClassLoader,从而扩展JVM的功能。 #### 二、ClassLoader...
了解 Java 类加载机制可以帮助我们更好地理解 Java 的运行机制,并且可以帮助我们更好地编写 Java 程序。 知识点总结: * Java 类加载机制是 Java 中一个非常重要的机制,它负责加载 Class 文件到 JVM,以供程序...
这个教程将深入探讨ClassLoader的工作原理、类型以及如何自定义类加载器。 一、Java ClassLoader 基础 1. 类加载过程:Java中的类加载分为三个阶段——加载、验证、准备、解析和初始化。ClassLoader主要参与的是...
通过对Java ClassLoader的深入了解,我们可以更好地理解Java类的加载机制以及如何通过自定义ClassLoader来满足特定的应用需求。淘宝网的成功实践为我们提供了宝贵的参考案例,展示了ClassLoaders在实际项目中的重要...
《深入Java虚拟机_ClassLoader》是一本专注于Java虚拟机(JVM)中ClassLoader部分的专著,旨在帮助读者深入理解Java程序如何加载、链接和初始化类。ClassLoader是Java平台核心特性的一部分,它负责查找和加载类到JVM...
Java ClassLoader 是一个重要的、但又常常被人忽略的 Java 运行时系统组件。它是负责在运行时查找和装入类文件的类。创建自己的 ClassLoader 可以以实用且有趣的方式定制 JVM,这样可以让您彻底重新定义如何将类文件...
ASM可以被用来创建Java代理、实现元编程、甚至深入到Java虚拟机(JVM)层面进行性能优化。在Java开发中,ASM库允许我们直接操作字节码,这对于理解和实践AOP(面向切面编程)的概念尤其有用,就像Spring框架中的AOP...
深入理解ClassLoader对于优化应用性能、处理类加载问题以及实现自定义加载策略至关重要。 一、ClassLoader 基本概念 1. 类加载器的层次结构:在Java中,类加载器形成了一个树形结构,通常由Bootstrap ClassLoader...