Перекомпилируйте байты прокси-класса [] (com.sun.proxy. $ Proxy0.class) в памяти в общий файл $ Proxy0.java. - PullRequest
0 голосов
/ 23 мая 2019

В JDK определенный прокси-класс был сгенерирован с помощью кода ниже в 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; at 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] == '\0')
            { 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 

    }
}

Моя цель - перекомпилировать байты прокси-класса [] (com.sun.proxy. $ Proxy0.class) в памяти в общий файл $ Proxy0.java

1 Ответ

0 голосов
/ 24 мая 2019

Subject.java

public interface Subject {
    public void rent();

    public void hello(String str);

    public void methodNotImpl();
}

ProxyGeneratorUtils.java // Чтобы сохранить файл класса прокси в локальном.

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

@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();
    }
}

Благодаря этим шагам мы точно знаем, как работает прокси , Нетнезависимо от того, какая функция определена в интерфейсе, который мы назвали, $ proxy0 сначала вызовет функцию invoke super.h.invoke () {} ;

Мы могли бы передать информацию о методе интерфейса объекту InvocationHandler (который использовался для создания прокси).

Затем мы могли бы сделать что угодно (включая вызов функции интерфейса) в функцию super.h.invoke () {}.

Если мы хотим вызвать функцию realSubject, нам просто нужно использовать полиморфизм, передавая объект RealSubject через method.invoke (realSubject, args);

Пожалуйста, знайте, что это выполнено тольковызов функции интерфейса субъекта и прокси объекта, а не класса

...