2010-01-10 8 views
24

Si tengo una instancia de Class en tiempo de ejecución, ¿puedo obtener su representación de byte []? Los bytes que me interesan estarían en el Class file format, de modo que serían una entrada válida para [ClassLoader.defineClass] [3].convert Objeto de clase a bytes

[3]: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html#defineClass(java.lang.String, byte [], int, int)

EDIT: He aceptado una respuesta getResourceAsStream, porque es muy simple y funciona la mayor parte del tiempo. ClassFileTransformer parece una solución más robusta porque no requiere que las clases se carguen desde archivos .class; manejaría clases cargadas en red, por ejemplo. Hay algunos aros para saltar con ese enfoque, pero lo tendré en cuenta. ¡Gracias a todos!

+0

Véase también http://stackoverflow.com/questions/7980133/converting-a-given-class-lets-say-java-lang-object- to-a-byte-array-is-it-po – Bozho

Respuesta

23

Por lo general, solo puede cargar la clase como un recurso del Classloader.

Class c = ... 
String className = c.getName(); 
String classAsPath = className.replace('.', '/') + ".class"; 
InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath); 

que probablemente recomendaría el uso de algo de Apache commons-io para leer el InputStream en un byte[], pero IOUtils.toByteArray() debería hacer el truco. Escribir ese código es realmente fácil equivocarse y/o hacerlo lento.

+0

y cómo compilar la clase en el otro lado cuando recibo este mensaje como 'ByteArrayInputStream'? –

+1

Crear clases desde bytes es el trabajo de un ClassLoader. –

+0

Hola, si la clase es una clase proxy y se genera dinámica en el tiempo de ejecución, y se almacena en la memoria, ¿cómo podemos guardarla en un archivo? –

2

En general, no se puede regresar así. Sin embargo, para algunos cargadores de clases, puede obtener el nombre completo de clase del archivo de recursos, reemplazando . con / y anexando .class (de modo que mypackage.MyClass se convierte en mypackage/MyClass.class (recuerde, puede distinguir entre mayúsculas y minúsculas)).

1

Interesante ...

Would cargar el ".class" como un archivo de los datos de entrada que necesita? En otras palabras, creo que necesita un archivo que haya sido compilado usando javac u otro compilador.

2

¡Puedes probar java instrumentation! ¡En particular, ClassFileTransformer puede ser de su interés!

Simplemente anula el método de transformación (de ClassFileTransformer), y se llamará a su método de transformación antes de cargar cada clase. Entonces puedes hacer cualquier clase de bytes.