2012-02-10 13 views
10

He estado usando Javassist para manipular dinámicamente las clases a medida que se cargan. Si bien agregar código a un método es relativamente fácil usando Javassist, no he podido encontrar una forma de eliminar el código .Eliminando instrucciones del bytecode de Java

En este momento estoy simulando la eliminación del código mediante el uso de nop instrucciones para reemplazar los códigos de operación específicos y los parámetros. Sin embargo, considero que esto sea sobre todo un truco:

  • Cada código de operación tiene que ser tratado por separado, ya que la longitud de bytes de los parámetros es diferente. En algunos casos, también tengo que elegir entre nop y pop, dependiendo de si el código de operación eliminado afecta a la pila o no. Este tipo de manipulación está empezando a ser tediosa, y el código que lo hace se está volviendo intrincado. Entonces, naturalmente, estoy esperando una solución existente.

  • El resultado final se rellena con nop instrucciones. Si bien la JVM debería optimizarlos sin impacto en el rendimiento, el bytecode resultante sigue siendo bastante poco elegante y más grande de lo que debería ser. Esto es más un problema de estética, pero todavía es algo a considerar.

Desafortunadamente, partes meramente cambiantes de la matriz de código de bytes para cerrar la brecha no es suficiente - las referencias al código movido (por ejemplo índices de instrucción de ramificación) deben ser actualizados también.

¿Es posible eliminar instrucciones usando Javassist? Alternativamente, ¿existe una biblioteca de manipulación de códigos de bytes que me permita hacerlo fácilmente, sin tener que analizar el bytecode?

+2

Solo tengo curiosidad. ¿Por qué quieres hacer esto? ¿No sería más fácil descompilar las clases, modificarlas y compilarlas de nuevo? – Luixv

+0

@Luixv: Deseo que el proceso de manipulación se realice automáticamente en el tiempo de ejecución; la modificación del código fuente real manualmente no es una opción, porque las transformaciones no son correctas. – thkala

+0

Si coloca la clase en un 'jar', el' nop' redundante se comprimirá bastante bien y el tamaño comprimido no será mucho mayor. –

Respuesta

3

Apache BCEL que permite a delete instructions:

Supresión de instrucciones también es muy sencillo; todos los identificadores de instrucciones y las instrucciones contenidas dentro de un rango determinado se eliminan de la lista de instrucciones y se eliminan. Sin embargo, el método delete() puede arrojar una TargetLostException cuando hay identificadores de instrucciones que aún hacen referencia a una de las instrucciones eliminadas. El usuario está obligado a manejar tales excepciones en una cláusula try-catch y redirigir estas referencias a otra parte.

Puede encontrar un ejemplo en el manual también.

+0

+1 No he visto BCEL todavía, pero suena prometedor. Veré cuán fácil sería incorporar en mi código existente ... – thkala

0

Desde el tutorial javassist:

Javassist no permite quitar un método o campo, sino que permite cambiar el nombre. Entonces, si un método ya no es necesario, debe renombrarse y cambiarse para que sea un método privado llamando a setName() y setModifiers() declarados en CtMethod.

+0

No quiero eliminar un método - Quiero eliminar las instrucciones de * dentro de * un método ... – thkala

+0

¡Uy, mi mal! Para mayor completidad, el tutorial también dice: 'Para eliminar un campo o un método, llame a removeField() o removeMethod() en CtClass.' : S – user1205938

Cuestiones relacionadas