2011-02-27 13 views
7

Quiero probar el nuevo verificador de código de tipo byte con las clases creadas por scalac.¿Cómo se emiten versiones de archivo de clase más nuevas con Scala (50.0/51.0)?

scalac muestra en la actualidad los archivos de clase de la versión 49.0, pero el nuevo verificador de verificación de tipo solo es obligatorio desde la versión 51.0.

Intenté "verificar" las clases con ProGuard (que de hecho las convirtió a la versión 50.0), pero no estoy seguro de si el verificador nuevo simplemente volvió al verificador de tipografía automática de forma automática.

¿Cómo puedo convertir archivos de clase a la versión 51.0 (o cómo puedo averiguar qué verificador se utiliza al cargar archivos de clase de la versión 50.0)?

Respuesta

2

Parece que FJBG (la biblioteca NSC utiliza para generar el código de bytes) ha visto alguna esfuerzo a apoyar StackMap pero no tengo ni idea de qué tan avanzado está.

Si preguntas en scala-internals, Stephane Michelou podría aparecer. Él es el tipo que ha estado working on it.

+0

¡Gracias! Tu respuesta fue bastante interesante y útil. – soc

1

No estoy seguro, pero creo que el formato de bytecode no se ha modificado profundamente y que probablemente siempre sea compatible con versiones anteriores. (Si sabe algo sobre bytecode, recuerde los largos y dobles en el pool constante y la pila de operandos, que fueron diseñados de una manera un poco loca. No ha sido modificado, ¿verdad?) Por lo tanto, probablemente cambie el número mayor/menor.

¿Cómo hacerlo? Hay dos formas:

  • Utilice el editor hexa y modifíquelo manualmente. Debería ser realmente simple si conoce la posición de los bytes. Ahí está la [especificación bytecode] [1], que dice que debe omitir los primeros cuatro bytes y verá dos bytes de versión menor y dos bytes de versión principal (en este orden).
  • Usa una biblioteca. Tengo algo de experiencia con BCEL. No parece ser la biblioteca mejor diseñada que he visto en mi vida, pero debería ser lo suficientemente buena para su caso. He visto los métodos setMinor y setMajor en una clase (mira ClassGen y la clase JavaClass "casi inmutable").

[1] http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

+3

No, esto no funcionará. 51.0 introduce un atributo StackMap obligatorio, que se utiliza con el verificador de verificación de tipo. Cambiar la versión no lo agregará. – soc

+0

Hmm, eso es interesante. He pensado que no es obligatorio. (No estoy hablando de un concepto similar en J2ME). Sin embargo, no entiendo la acción de "preverificación" que hiciste. Si fue el J2ME preverify, no convertiría en mi humilde opinión el classfile a esa nueva versión. Si fuera el concepto más nuevo, debería convertirlo a 51.0 y no a 50.0. Por cierto, también puedes verificar la biblioteca/herramientas de ASM. Lo he usado para algunas verificaciones de código de bytes durante la depuración y pude inferir los tipos de pila de operandos, por lo que la generación de StackMap se puede construir en este IMHO simplemente. – v6ak

1

me gustaría utilizar ASM para analizar el código de bytes. Sé que scala (y clojure) usan ASM internamente, por lo que el esfuerzo dedicado a aprenderlo no se desperdiciará. Probablemente pueda juntar un ClassReader y un EmptyVisitor que anule el método de visita que proporciona la información del encabezado con bastante rapidez.

+0

scala no usa ASM internamente. – extempore

+0

Incluso pensé en verificarlo en línea antes de decirlo. Aparentemente solo el scala [eclipse plugin] (https://codereview.scala-lang.org/fisheye/qsearch?q=org.objectweb.asm). Mis aplicaciones para el error. – Matt

0

Sé que puede ser obvio, pero no estoy seguro de que después de leer tu pregunta para que voy a preguntar:

¿Está utilizando una versión beta construir? Al igual que en una de las construcciones nocturnas? ¿O quieres modificar la versión actual?

EDITAR: Ok, hay algo que no entiendo aquí. Acabo de probar las versiones nocturnas y sí, son la versión 49.0. Pero hasta donde sé, esto es establecido por el compilador.

Está intentando cambiar la versión para tener acceso a nuevas funcionalidades sofisticadas. Pero eso no tiene sentido para mí. Si el compilador lanza la versión 49.0, cambiarla a una versión más nueva (50.0, 51.0 o 70.0 por lo que importa) no debería tener ningún impacto. Por lo que yo sé, la versión es para garantizar la compatibilidad, lo que significa que no ejecutará una clase más nueva con una máquina virtual más antigua que no sea compatible con su idioma.

Por lo tanto, en su caso, agregar una nueva versión significará que, probablemente, la VM actual no querrá ejecutar su código. E incluso si lo hace, probablemente no contenga la funcionalidad que menciona, si esa funcionalidad solo está en la versión 51.0 que su compilador/VM actual no admite.

Quiero decir, tal vez lo que estás tratando de hacer es completamente normal y es simplemente que no lo sé y estoy demostrando mi ignorancia en esta área :), pero creo que falta algo allí.

+0

Estoy usando el tronco actual 2.9. – soc

0

Supongo que una de las cosas más fáciles de hacer sería usar un descompilador de Java (ver JADClipse para un plugin de Eclipse) y luego recompilar la fuente a la versión que necesites.

+1

No creo que vaya a sobrevivir al viaje de ida y vuelta entre Scala source -> bytecode -> Java source -> bytecode. No todo en Scala se puede traducir a Java. – soc

Cuestiones relacionadas