Red de conocimiento informático - Problemas con los teléfonos móviles - Cómo lidiar con la versión 52.0 de major.minor no compatible

Cómo lidiar con la versión 52.0 de major.minor no compatible

1: Problemas que deben resolverse con urgencia

Después de haber probado los beneficios de JDK1.5, creo que muchas personas encontraron el error Unsupported major.minor versión 49.0 y estaban perdidas en ese momento. . Porque al principio no había mucha información china relacionada con esto en Internet. Ahora, puedes encontrar cómo resolverlo buscando en línea. La mayoría te indicará que vuelvas a compilar con JDK 1.4. En cuanto a por qué, ¿qué es mayor.menor? De eso se trata esta publicación de blog para que lo sepas antes de cometer un error.

Supongo que tuve suerte porque antes de encontrarme con este error, había leído "Dentro de la máquina virtual Java" (segunda edición) y sabía dónde se escondía major.minor, pero no lo he experimentado. así que tendré que esperar hasta tener la oportunidad de lidiar con major.minor no compatible. Realmente habrá una entrevista con la versión 49.0 major.minor no compatible, solo para verificar un hecho por mí.

En primer lugar, debemos establecer una idea directa de la versión 49.0 de major.minor no compatible: las clases compiladas de JDK1.5 no se pueden ejecutar en JVM 1.4 y deben compilarse en JVM 1.4 para ejecutarse. (Por supuesto, tal vez todavía esté usando JVM 1.3 o JVM 1.2, por lo que debe compilar en una clase que la JVM de destino pueda reconocer). Así es como se soluciona el problema.

Dos: ¿Dónde se encuentra major.minor?

¿Qué es major.minor y dónde se encuentra? Primer sentido y encontrar mayor.menor.

Escriba un fragmento de código Java Hello World y luego use el compilador JDK 1.5 para compilarlo en HelloWorld.java

paquete com.unmi

; clase pública Hola Mundo

{

public static void main(String[] args)

{

System.out.println(" ¡Hola mundo!");

}

}

paquete com.unmi; clase pública HolaMundo{ public static void main(String[] args) { System.out .println("¡Hola mundo!"); }}

Utilice JDK 1.5 javac -d para compilar HelloWorld.java. Utilice UltraEdit para abrir el código de bytes compilado de HelloWorld.java. El contenido de HelloWorld.class se muestra en la figura:

En la figura anterior podemos ver cuál es la versión mayor.menor, que es equivalente a. la versión principal de un software y el número de versión secundaria, pero aquí está el número de versión principal y el número de versión secundaria que identifican una clase Java. Al mismo tiempo, vemos que versión_menor es 0x0000, versión_mayor es 0x0031, convertidos en diez. dígitos, es decir, 0 y 49, es decir, mayor.menor es 49,0.

3. ¿Qué es mayor.menor? ¿Qué es major.minor y para qué se utiliza?

Los bytes 5-8 del archivo de clase son minor_version y major_version. A medida que cambia el formato del archivo de clase, el número de versión también cambiará.

Para la JVM, el número de versión identifica un formato de archivo de clase específico y, por lo general, la JVM solo puede leer un archivo de clase si obtiene un número de versión principal y un conjunto de números de versión menores. Si el número de versión de un archivo de clase excede el rango válido que la JVM puede procesar, la JVM no procesará el archivo de clase.

En la versión JDK 1.0.2 de Sun, la JVM implementó soporte para formatos de archivos de clase 45.0 a 45.3. Todas las JVM en JDK 1.1 admiten las versiones 45.0 a 45.65535 del formato de archivo de clase. En la versión 1.2 SDK de Sun, la JVM admite las versiones 45.0 a 46.0 del formato de archivo de clase.

Un compilador versión 1.0 o 1.2 puede generar archivos de clase versión 45.3. En la versión 1.2 del SDK de Sun, el compilador Javac genera archivos de clase con la versión 45.3 de forma predeterminada. Sin embargo, si se especifica el indicador -target 1.2 en la línea de comando javac, un compilador de la versión 1.2 generará archivos de clase con el número de versión 46.0. Los archivos de clase generados con el indicador -target 1.2 no se ejecutarán en las versiones 1.0 o 1.1 de JVM.

En la versión 2 de la implementación JVM, la interpretación de los números de versión mayor y menor del archivo de clase cambió. En la versión 2, el número de versión principal de un archivo de clase es consistente con el número de versión de la versión principal de la plataforma Java (por ejemplo, en la versión de la plataforma Java 2, el número de versión principal aumenta de 45 a 46), mientras que el número de versión secundaria es coherente con el número de versión de la versión principal específica. Cada versión de la plataforma está asociada. Por lo tanto, aunque diferentes formatos de archivos de clase pueden representarse mediante diferentes números de versión, diferentes números de versión no significan que los formatos de archivos de clase sean diferentes. El motivo de los diferentes números de versión puede ser simplemente que estos archivos de clase fueron generados por diferentes versiones de la plataforma Java y es posible que el formato de los archivos de clase no haya cambiado.

Los tres párrafos anteriores están extraídos de "Comprensión profunda de la máquina virtual Java", que es muy detallado. JDK 1.2 abrió la era de Java 2, pero esa era aún está lejos de nosotros. Muchos de nosotros saltamos directamente a JDK 1.4, y yo era más o menos igual, pero los requisitos del proyecto tenían que fijarse en JDK 1.3. Pero la información general que podemos obtener es que los archivos de clase compilados por cada versión del compilador JDK tienen un número de versión, y diferentes JVM pueden aceptar un cierto rango de números de versión de clase, y se producirá un error si exceden el rango. Pero esto es generalmente compatible con versiones anteriores. ¿Conoces el eslogan de Solaris de Sun? Mantener una compatibilidad binaria del 100 % con versiones anteriores protege las inversiones de los clientes.

Cuatro: Otros métodos para determinar la versión mayor.menor de una clase

1) Vista de Eclipse

Eclipse 3.3 agrega una nueva característica, cuando una clase lo hace no coincide Cuando el código fuente está asociado, al abrirlo se mostrará información más detallada sobre la clase. Por supuesto, aún no ha alcanzado el nivel de código fuente. La siguiente imagen muestra la vista de abrir una versión 2.0 de spring.jar en ClasspathXml. Información mostrada por ClasspathXml.spring.jar ClasspathXmlApplicationContext.class en spring.jar

2) Comando javap -verbose

Para archivos de clase compilados, use javap -verbose para mostrar la clase principal. versión menor, vea la figura a continuación:

3) El comando javap -verbose -verbose -verbose -verbose puede mostrar la versión mayor.menor de la clase.

Vea la imagen a continuación:

3) Archivo MANIFEST

Cuando la clase se coloca en el paquete JAR, habrá un archivo META-INF/MANIFEST. Este archivo generalmente tiene información del compilador. , como se enumera a continuación. El contenido de los archivos META-INF/MANIFEST de varios paquetes se publica para que todos puedan verlo

La parte META-INFO/MANIFEST de -Velocity -Velocity -1.5.jar

Versión del manifiesto: 1.0

Versión Ant: Apache Ant 1.7.0

Creado por: Apache Ant

Paquete: org.apache. velocidad

Build -Jdk: 1.4.2_08

Extensión: velocidad

Podemos ver que está empaquetado con ant, y el JDK utilizado para construirlo es 1.4.2_08, por lo que se usa 1.4. Las clases compiladas, por supuesto, se ejecutarán en 1.4. Por supuesto, la JVM ejecutará clases compiladas con 1.4 en una JVM 1.4. Sería aburrido si este tipo compilara con 1.5 JDK y luego lo empaquetara con JDK 1.4+ANT.

-2.0 Sección META-INFO\MANIFEST de spring.jar

Versión de manifiesto: 1.0

Versión de Ant: Apache Ant 1.6.5

Creado por: 1.5.0_08 -b03 (Sun Microsystems Inc.)

Título de implementación: Ahora tenga en cuenta que está compilado con JDK 1.5, por lo que viene con -target 1.4 o -objetivo 1.3? Sí, puedes verificar el binario de la clase, eso es lo más seguro. b28 (Sun Microsystems Inc.)

Construido con JDK 1.4.

El primer y segundo método pueden comprender claramente la versión mayor.menor. El tercer método no debería ser un problema, pero si encuentra compilaciones anormales, por ejemplo, cambie META-INFO\MANIFEST Empaquetado y cámbielo. es difícil saberlo. Un enfoque directo para observar el archivo binario garantizaría la precisión y también aceptaría el hecho de que fue manipulado por herramientas.

Cinco: Comparación del compilador y el meollo del problema

Ahora puede ser la versión menor.mayor predeterminada de las clases compiladas por el compilador JDK 1.1 a JDK 1.7.

(Luego fui al sitio web de Sun para buscar antigüedades antiguas que nunca había usado)

Parámetro de destino de la versión del compilador JDK hexadecimal minor.major decimal minor.major

jdk1.1.8 no puede aceptar el parámetro de destino 00 03 00 2D 45.3

jdk1.2.2 sin (el valor predeterminado es -target 1.1) 00 03 00 2D 45.3

jdk1.2.2 -target 1.2 00 00 00 2E 46.0

jdk1.3.1_19 sin (el valor predeterminado es -target 1.1) 00 03 00 2D 45.3

jdk1.3.1_ 19 -target 1.3 19 -target 1.3 00 00 00 2F 47.0

j2sdk1.4.2_10 sin (el valor predeterminado es -target 1.2) 00 00 00 2E 46.0

j2sdk1.4.2_10 -target 1.4 00 00 00 30 48.0

jdk1.5.0 ._11 sin (el valor predeterminado es -target 1.5) 00 00 31 49.0

jdk1.5.0_11 -target 1.4 -source 1.4 00 00 30 48.0

jdk1.6.0_01 sin (el valor predeterminado es -objetivo 1.6) 00 00 00 32 50.0

jdk1.6.0_01 -objetivo 1.5 00 00 00 31 49.0

jdk1.6.0 _01 -objetivo 1.4 -fuente 1.4 00 00 30 48.0

jdk1.7.0 sin (el valor predeterminado es -target 1.6) 00 00 32 50.0

jdk1.7.0 -target 1.7 00 00 33 51.0

jdk1 .7.0 -target 1.4 -source 1.4 00 00 00 30 48.0

Apache Harmony 5.0M3 sin (el valor predeterminado es -target 1.2) 00 00 2E 46.0

Apache Harmony 5.0M3 -target 1.4 00 00 00 30 48.0

Lo anterior es una comparación de compiladores JDK en la plataforma Windows. Podemos resumirlo aquí:

1) -target 1.1 Tiene un número de versión menor. El objetivo es la versión 1.2 y posteriores, solo se utiliza el número de versión principal y el número de versión secundaria es 0

2) La diferencia de idioma de 1.1 a 1.4 es relativamente pequeña, por lo que el objetivo predeterminado de 1.2 a 1.4 no es la versión en sí misma

3) La sintaxis de 1.5 ha cambiado mucho, por lo que el destino predeterminado es 1.5. Debido a esto, un JDK 1.5 debe crear objetivos para 1.5, que es la versión más popular. Para usar el JDK 1.5 para generar código destinado a 1.4, simplemente -target 1.4 no es suficiente. También debe traer -source 1.4 para especificar la compatibilidad del código fuente. El código generado por el JDK 1.6/1.7 también es 1.4.

4) El compilador 1.6 es más agresivo y usa -target 1.6 por defecto.

5) Tenga en cuenta que el destino predeterminado para la compilación 1.7 es 1.6

6) Otros terceros

6) El formato de los archivos de clase generados por otros terceros -party JDK es el mismo que La versión correspondiente de Sun del JDK es la misma

7) Finalmente, y lo más importante, es necesario comparar entre 1.6 y 1.5. Finalmente, y lo más importante, la versión principal más grande de un archivo de clase que una versión particular de la JVM puede aceptar no debe ser mayor que la versión del archivo de clase que el JDK correspondiente compiló con los parámetros de destino correspondientes.

La oración anterior es un poco larga y no es fácil de leer de una vez, así que aquí hay un ejemplo: El número máximo de versión principal de un archivo de clase aceptado por la JVM 1.4 no puede ser mayor que la clase compilada. por el JDK 1.4 usando el parámetro -target 1.4 El número de versión principal del archivo, que es 48.

Dado que el destino predeterminado es 1.5, los archivos generados no excederán el número de versión principal del archivo de clase compilado con el JDK correspondiente usando el parámetro -target 1.5 y, por lo tanto, no excederán 48.

Entonces, cuando el JDK se actualiza de 1.1 a 1.2, 1.2 a 1.3 o 1.3 a 1.4, ¿por qué no aparece el error de versión mayor.menor no compatible? Esto se debe a que 1.2/1.3/1.4 mantiene una buena compatibilidad binaria. Los objetivos de 1.2/1.3/1.4 son 1.1/1.1/1.2 respectivamente. En otras palabras, los archivos de clase compilados por el JDK 1.4 de forma predeterminada se pueden cargar y ejecutar en JVM 1.2, y mucho menos en JVM 1.3. (

Seis: encuentre una solución al problema

Así que ahora, si encuentra este problema y sabe cómo resolverlo, también puede encontrar un JDK 1.4, descargarlo e instalarlo. y luego usarlo para recompilar todo el código, como vi que hicieron algunos de mis amigos. De hecho, no tiene por qué ser tan problemático. Todos deben recordar que hay un parámetro -target en javac. Puede continuar usando el JDK 1.5 y compilar con los parámetros -target 1.4 -source 1.4. Sin embargo, debe saber qué API se agrega al JDK 1.5. No puede transferir sus archivos de clase a JVM 1.4. , la opción de compilación es -target 1.3 -source 1.3

En consecuencia, si usa ant, su tarea javac también puede corresponder a la selección de código fuente y de destino

Si está desarrollando, Es seguro decir que ahora existen IDE de JAVA que tienen opciones de compilación que configuran el código de destino para el proyecto, por ejemplo, en la configuración del compilador de Java en las propiedades del proyecto de Eclipse, como se muestra en la figura.

En las opciones del compilador autoconfiguradas, verá los diferentes niveles de cumplimiento del compilador que se pueden seleccionar, la compatibilidad del archivo de clase generado y la compatibilidad del código fuente también cambian constantemente. La compatibilidad del archivo de clase generado y la compatibilidad del código fuente también cambian constantemente. También puede ajustar estos dos elementos manualmente. No tiene que preocuparse por la versión del compilador al configurarlos manualmente. Sí, solo pídale que genere el código de bytes que queremos y luego expanda. está escrito en VB, no importa siempre que se pueda compilar en un código de bytes que pueda ser ejecutado por la JVM. También puede hacerlo de otras maneras. Busque el cuadro de diálogo de configuración correspondiente en el entorno de desarrollo integrado. p>

De lo contrario, debe conocer la versión de la JVM que está utilizando actualmente y los números de versión principal del código de bytes que acepta (consulte la tabla anterior).

Hay dos formas de averiguar la versión actual de JVM:

Primero, si usa el comando java para ejecutar el programa directamente desde la consola, puede usar java -version para ver la versión actual de JVM y luego determine cuál es aceptable. Versión del archivo de clase

En segundo lugar, si ejecuta el programa en un contenedor y no sabe qué JVM está utilizando, puede agregar el código System.getProperty("java. runtime.version"); o System. getProperty("java.class.version") para obtener la versión de JVM y los números de versión de clase aceptables.

Un último consejo es si no deseas recompilar todo tu código para una versión inferior de la JVM con parámetros de destino; si aún deseas continuar usando la nueva API en tu código o algo peor; Si está utilizando las nuevas características de JDK 1.5, como genéricos, desempaquetado automático, enumeraciones, etc., entonces no puede compilar su código, entonces no puede usar -target 1.4 -source 1.4 para compilar su código, pero debe ser Código reorganizado para que funcione correctamente. Entonces déjame contarte el último truco: no necesitas comenzar desde el código fuente, convertir directamente tu código de bytes compilado normalmente y continuar disfrutando de esas nuevas características y nuevas API, es decir: consulta un blog anterior: Retrotranslator Le permite usar las funciones de JDK1.5 para escribir código que se puede ejecutar en JVM1.4. Así es como lo uso, no habrá problemas. Yo lo estoy usando y si pruebas bien no deberías tener ningún problema.

Siete: Otro problema relacionado que realmente ocurrió

Este es un error que no admite la versión 49.0 de major.minor al copiar Tomcat. Esto es lo que sucedió: instalé JDK 1.5 localmente, luego encontré un instalador EXE Tomcat en línea, lo instalé y funcionó bien. Más tarde, un colega quería un Tomcat pero no quería descargarlo ni instalarlo, así que, según mi experiencia pasada, simplemente le copié todo el directorio de mi Tomcat. Como resultado, todos los archivos jsp que buscó eran importantes no compatibles. Errores menores de la versión 49.0. Debe haber instalado JDK 1.4, pero todavía estoy un poco desconcertado. Todavía estaba un poco desconcertado y me eché a reír. Antes tenía mucha confianza en este problema. El pensamiento habitual es que tal excepción ocurrirá cuando los archivos de clases compilados se usen en una versión inferior de JVM, pero ahora no es posible usar las clases compiladas por JDK 1.5 para la ejecución.

Más tarde, leí el mensaje de excepción detenidamente y finalmente descubrí la pista %TOMCAT_HOME%\common\lib\tools.jar, debido a que el archivo jsp necesita ser compilado por él, así que escribí un archivo de clase en este tools.jar ¡Una mirada, 49.0, y rápidamente me di cuenta de que este archivo estaba en mi máquina! Al instalar Tomcat, el programa de instalación de Tomcat copia desde el directorio %JDK1.5%\lib al directorio lib de Tomcat. Como resultado, al compilar JSP en la máquina de un colega, es una JVM 1.4 con un archivo tools.jar 49.0, así que nada. puede salir mal, así que busque tools.jar de JDK 1.4 y reemplace Tomcat y todo estará bien.

Ocho: Resumen

De hecho, entender major.minor es como podemos imaginar que es imposible que una aplicación de 32 bits se ejecute en un sistema de 16 bits si También es un programa de Microsoft. Ejecútalo.

Si conocemos la versión de la JVM de destino antes de publicarla y sabemos cómo distinguir la versión mayor.menor del archivo de clase Java, entonces no tenemos que esperar a que el servidor informe la excepción. antes de solucionarlo, y también podemos anticiparnos a los problemas que puedan surgir.

Cuando se encuentre con este tipo de problema en otros momentos, debe resolverse de manera específica. En resumen, la causa principal del problema es que la versión inferior de la JVM no puede cargar la versión superior. archivo de clase. El archivo de clase debe encontrar una versión superior del archivo de clase para procesarlo.