将内存中的proxy class bytes[] (com.sun.proxy.$Proxy0.class)重新编译为通用的$Proxy0.java文件
Recompile the proxy class bytes[] (com.sun.proxy.$Proxy0.class) in memory to a general $Proxy0.java file
在 JDK 中,特定代理 class 是由 Proxy.java
中的以下代码生成的
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
现在我已经获取了 byte[] proxyClassFile,我想使用 JNI 函数 defineClass0 并重新生成特定的代理。
错误如下:
线程 "main" java.lang.UnsatisfiedLinkError 异常:util.DefineClass.cloader.defineClass0(Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class;
在 util.DefineClass.cloader.defineClass0(本机方法)
我的文件如下:
Test.java
public class test {
public static void main(String[] args) throws java.lang.Exception
{
]
Class testc;
Object testo;
cloader cl=new cloader();
testc=cl.load("com.sun.proxy.$Proxy0");
testo=testc.newInstance();
....
}
}
cloader.java
class cloader extends ClassLoader {
public native Class<?> defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);
static {
try {
System.loadLibrary("java");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
System.exit(1);
}
}
public static int returnActualLength(byte[] data) {
int i = 0;
for (; i < data.length; i++) {
if (data[i] == '[=16=]')
{ break;}
}
return i;
}
public Class load(String classname) throws java.lang.Exception
{
try {
Class ctmp=this.findLoadedClass(classname);
System.out.println(ctmp.getName()+ " is load");
return ctmp;
}
catch (Exception e) {
}
byte[] classbyte = {........};
int readsize;
readsize=returnActualLength(classbyte);
return defineClass0(ClassLoader.getSystemClassLoader(), "com.sun.proxy.$Proxy0",classbyte, 0, readsize);//there be error
}
}
我的目标是将内存中的代理 class bytes[] (com.sun.proxy.$Proxy0.class) 重新编译为通用的 $Proxy0.java 文件
Subject.java
public interface Subject {
public void rent();
public void hello(String str);
public void methodNotImpl();
}
ProxyGeneratorUtils.java //保存代理class文件到本地
public class ProxyGeneratorUtils {
public static void writeProxyClassToHardDisk(String path) {
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", RealSubject.class.getInterfaces());
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
测试
@Test
public void testGenerateProxyClass() {
ProxyGeneratorUtils.writeProxyClassToHardDisk("/Desktop/temp/$Proxy0.class";
}
}
使用一些工具反编译$Proxy0.class并获得
$Proxy0.java
import com.AnotherExample.*;
import java.lang.reflect.*;
public final class $Proxy0 extends Proxy implements Subject
{
private static Method m1;
private static Method m4;
private static Method m5;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(final InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final boolean equals(final Object o) {
try {
return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void rent() {
try {
super.h.invoke(this, $Proxy0.m4, null);//*****
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void methodNotImpl() {
try {
super.h.invoke(this, $Proxy0.m5, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String toString() {
try {
return (String)super.h.invoke(this, $Proxy0.m2, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void hello(final String s) {
try {
super.h.invoke(this, $Proxy0.m3, new Object[] { s });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final int hashCode() {
try {
return (int)super.h.invoke(this, $Proxy0.m0, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
static {
try {
$Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
$Proxy0.m4 = Class.forName("com.AnotherExample.Subject").getMethod("rent", (Class<?>[])new Class[0]);
$Proxy0.m5 = Class.forName("com.AnotherExample.Subject").getMethod("methodNotImpl", (Class<?>[])new Class[0]);
$Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
$Proxy0.m3 = Class.forName("com.AnotherExample.Subject").getMethod("hello", Class.forName("java.lang.String"));
$Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
}
catch (NoSuchMethodException ex) {
throw new NoSuchMethodError(ex.getMessage());
}
catch (ClassNotFoundException ex2) {
throw new NoClassDefFoundError(ex2.getMessage());
}
}
}
Client.java //供参考
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client
{
public static void main(String[] args)
{
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);//handler own the realSubject's information
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
subject.methodNotImpl();
}
}
通过这些步骤我们知道Proxy具体是如何工作的,
无论我们调用接口中定义的什么函数,$proxy0都会先调用invoke函数super.h.invoke(){};
我们可以将接口的Method信息传递给InvocationHandler对象(用于构造代理)
然后我们可以在函数super.h.invoke(){}中做任何事情(包括调用接口的函数)。
如果我们想调用 realSubject 的函数,我们只需要使用多态性通过 method.invoke(realSubject, args);
传递一个 RealSubject 对象
请注意,这只是调用 Subject 接口的函数并代理对象而不是 Class
在 JDK 中,特定代理 class 是由 Proxy.java
中的以下代码生成的 /*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
现在我已经获取了 byte[] proxyClassFile,我想使用 JNI 函数 defineClass0 并重新生成特定的代理。
错误如下:
线程 "main" java.lang.UnsatisfiedLinkError 异常:util.DefineClass.cloader.defineClass0(Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class; 在 util.DefineClass.cloader.defineClass0(本机方法)
我的文件如下:
Test.java
public class test {
public static void main(String[] args) throws java.lang.Exception
{
]
Class testc;
Object testo;
cloader cl=new cloader();
testc=cl.load("com.sun.proxy.$Proxy0");
testo=testc.newInstance();
....
}
}
cloader.java
class cloader extends ClassLoader {
public native Class<?> defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);
static {
try {
System.loadLibrary("java");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
System.exit(1);
}
}
public static int returnActualLength(byte[] data) {
int i = 0;
for (; i < data.length; i++) {
if (data[i] == '[=16=]')
{ break;}
}
return i;
}
public Class load(String classname) throws java.lang.Exception
{
try {
Class ctmp=this.findLoadedClass(classname);
System.out.println(ctmp.getName()+ " is load");
return ctmp;
}
catch (Exception e) {
}
byte[] classbyte = {........};
int readsize;
readsize=returnActualLength(classbyte);
return defineClass0(ClassLoader.getSystemClassLoader(), "com.sun.proxy.$Proxy0",classbyte, 0, readsize);//there be error
}
}
我的目标是将内存中的代理 class bytes[] (com.sun.proxy.$Proxy0.class) 重新编译为通用的 $Proxy0.java 文件
Subject.java
public interface Subject {
public void rent();
public void hello(String str);
public void methodNotImpl();
}
ProxyGeneratorUtils.java //保存代理class文件到本地
public class ProxyGeneratorUtils {
public static void writeProxyClassToHardDisk(String path) {
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", RealSubject.class.getInterfaces());
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
测试
@Test
public void testGenerateProxyClass() {
ProxyGeneratorUtils.writeProxyClassToHardDisk("/Desktop/temp/$Proxy0.class";
}
}
使用一些工具反编译$Proxy0.class并获得 $Proxy0.java
import com.AnotherExample.*;
import java.lang.reflect.*;
public final class $Proxy0 extends Proxy implements Subject
{
private static Method m1;
private static Method m4;
private static Method m5;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(final InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final boolean equals(final Object o) {
try {
return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void rent() {
try {
super.h.invoke(this, $Proxy0.m4, null);//*****
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void methodNotImpl() {
try {
super.h.invoke(this, $Proxy0.m5, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String toString() {
try {
return (String)super.h.invoke(this, $Proxy0.m2, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void hello(final String s) {
try {
super.h.invoke(this, $Proxy0.m3, new Object[] { s });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final int hashCode() {
try {
return (int)super.h.invoke(this, $Proxy0.m0, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
static {
try {
$Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
$Proxy0.m4 = Class.forName("com.AnotherExample.Subject").getMethod("rent", (Class<?>[])new Class[0]);
$Proxy0.m5 = Class.forName("com.AnotherExample.Subject").getMethod("methodNotImpl", (Class<?>[])new Class[0]);
$Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
$Proxy0.m3 = Class.forName("com.AnotherExample.Subject").getMethod("hello", Class.forName("java.lang.String"));
$Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
}
catch (NoSuchMethodException ex) {
throw new NoSuchMethodError(ex.getMessage());
}
catch (ClassNotFoundException ex2) {
throw new NoClassDefFoundError(ex2.getMessage());
}
}
}
Client.java //供参考
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client
{
public static void main(String[] args)
{
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxy(realSubject);//handler own the realSubject's information
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
subject.methodNotImpl();
}
}
通过这些步骤我们知道Proxy具体是如何工作的, 无论我们调用接口中定义的什么函数,$proxy0都会先调用invoke函数super.h.invoke(){};
我们可以将接口的Method信息传递给InvocationHandler对象(用于构造代理)
然后我们可以在函数super.h.invoke(){}中做任何事情(包括调用接口的函数)。
如果我们想调用 realSubject 的函数,我们只需要使用多态性通过 method.invoke(realSubject, args);
传递一个 RealSubject 对象请注意,这只是调用 Subject 接口的函数并代理对象而不是 Class