2010-09-03 16 views
14

tengo este proyecto hecha de múltiples frascos y guerra para hacer una oreja. Construyo todo en una instantánea y funciona muy bien. Entonces hice una liberación para cada proyecto y vi que los frascos y la guerra eran ligeramente diferentes en tamaño que los de instantáneas.Maven versión plugin: especificar el compilador Java versión

archivo Comparando a presentar me di cuenta de que los archivos .class estaban todos allí, pero un poco más grande o más grande, nada más que 40 bytes en general.

fuerzo compilación de utilizar Java 1.5 utilizando esta etiqueta en Maven:

<build> 
    <pluginManagement> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>2.0.2</version> 
       <configuration> 
        <source>1.5</source> 
        <target>1.5</target> 
       </configuration> 

utilizo esta etiqueta para la liberación plugin:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-release-plugin</artifactId> 
    <version>2.0</version> 
    <configuration> 
     <releaseProfiles>release</releaseProfiles> 
     <goals>deploy</goals> 
    </configuration> 
</plugin> 

Podría ser que el plugin de liberación está recopilando en 1.6 u otro, explicando la diferencia de tamaño de las clases? Si es así, ¿puedo hacer que el plugin de lanzamiento compile en 1.5?

Gracias por su aportación.

+0

Si intenta ejecutar los archivos liberados en 1.5, ¿se ejecutan en 1.5? ¿O recibe una excepción jar no válida/jar dañado, diciéndole que probablemente fueron compilados en una versión posterior? – aperkins

+0

Tanto la instantánea como los archivos de liberación parecen estar funcionando, ejecutándose en 1.5. Todavía no recibo ningún error, pero no entiendo por qué las clases tienen un tamaño diferente. Solo espero que algo no vaya a saltar sobre mí cuando llegue a producción. – IceGras

+0

@IceGras, podría ser peligroso, explico por qué en mi respuesta a continuación ... En resumen, las referencias a métodos inexistentes pueden incluirse_ – Lucas

Respuesta

1

puede comprobar la versión de una clase es compilado por el uso de la utilidad javap incluido con el JDK. Desde la línea de comandos:

javap -verbose MyClass 

En la salida de la mirada javap para "versión menor" y "versión principal" sobre diez líneas más abajo.

A continuación, utilice esta tabla:

 
major  minor  Java platform version 
45   3   1.0 
45   3   1.1 
46   0   1.2 
47   0   1.3 
48   0   1.4 
49   0   1.5 
50   0   1.6 

El .class diferencia de tamaño puede ser debido a compilar la versión pero también puede ser debido a otras opciones de compilación como compilar con información de depuración (números de línea en stacktraces).

+0

En macOS (10.12.6 como mínimo), el resultado del ** archivo * * comando es aún más útil, por ejemplo 'file MyClass.class' podría producir:' MyClass.class: compiled Java class data, version 50.0 (Java 1.6) ' – Gary

0

Could it be that the release plugin is compiling in 1.6 or other, explaining the classes size difference ?

No se puede IMO. El lanzamiento Maven Plugin no compila nada, sólo desencadena una fase que sí desencadenar la fase compile y el Maven plugin del compilador. En otras palabras, se usará el plugin Maven Compiler y su configuración.

Se pueden utilizar los siguientes comandos para controlar lo que está ocurriendo exactamente:

mvn help:active-profiles -Prelease 

para comprobar perfiles. Y

mvn help:effective-pom -Prelease 

para comprobar el pom eficaz.

+0

Tengo el mismo problema. Tengo '' y '' especificados en mi archivo pom como 1.6. Cuando ejecuto 'mvn package' obtengo un éxito. Sin embargo, cuando ejecuto 'mvn release: prepare' falla con el error' TunneledDataSourceWrapper.java:[17,7]: TunneledDataSourceWrapper no es abstracto y no anula el método abstracto getParentLogger() en CommonDataSource', que es una indicación de que está intentando para compilar java 7 _ (java 7 agregó un método a CommonDataSource por lo que es incompatible con 6) _. – Lucas

18

--- --- SPOILER ALERT

La respuesta corta es que con el fin de compilar código fuente de una versión anterior, es necesario proporcionar tanto la opción -source así como la -bootclasspath. Ver this article. Y si se desea compilar fuente a una nueva versión, es necesario establecer <source>, <target>, <compilerVersion>, <fork>, y <executable> en el plugin del compilador, y establecer <jvm> en el plugin segura ...

y ahora para la historia ...

Me encontré con el mismo problema. Resulta que compilar una versión anterior puede no ser tan fácil como configurar <source> y <target>. Mi caso específico es que tengo un Java 1.7 JDK y que mi clase tiene una incompatibilidad con 1.7 (agregaron un nuevo método a una interfaz que estoy implementando). Cuando traté de compilarlo, el compilador me dio un mensaje de error que decía que no había implementado el método de interfaz. De todos modos, he intentado configurar el plugin del compilador:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <version>2.3.2</version> 
    <configuration> 
     <source>1.6</source> 
     <target>1.6</target> 
     <encoding>UTF-8</encoding> 
    </configuration> 
    </plugin> 

pero cuando me encontré con la construcción, me dieron el mismo error. Así que corrí experto en depuración y vi esto:

[INFO] [DEBUG] Command line options: 
[INFO] [DEBUG] -d C:\... -nowarn -target 1.6 -source 1.6 -encoding UTF-8 

Tenga en cuenta que la ... se pone en su lugar de argumentos reales en aras de la brevedad

en la salida. El mensaje que comienza con -d es la lista de argumentos de compilación completa real. Por lo tanto, si se quita la bandera -nowarn y pegar el resto después de javac en la línea de comandos se puede ver la salida real del compilador:

javac -d C:\... -target 1.6 -source 1.6 -encoding UTF-8 
warning: [options] bootstrap class path not set in conjunction with -source 1.6 

Esto muestra la advertencia ruta de clase arranque práctico-excelente no ocupa conjunción con -fuente 1.6. Un poco de googling en que se vuelve a this article que establece:

To use javac from JDK N to cross-compiler to an older platform version, the correct practice is to:

  • Use the older -source setting.
  • Set the bootclasspath to compile against the rt.jar (or equivalent) for the older platform.

If the second step is not taken, javac will dutifully use the old language rules combined with new libraries, which can result in class files that do not work on the older platform since references to non-existent methods can get included.

ahora referencia a the maven documentation for the compiler plugin da:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <version>2.5.1</version> 
    <configuration> 
     <compilerArguments> 
     <verbose /> 
     <bootclasspath>${java.home}\lib\rt.jar</bootclasspath> 
     </compilerArguments> 
    </configuration> 
    </plugin> 

que luego se puede combinar con la configuración anterior para obtener:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <version>2.3.2</version> 
    <configuration> 
     <source>1.6</source> 
     <target>1.6</target> 
     <encoding>UTF-8</encoding> 
     <bootclasspath>${java.home}\lib\rt.jar</bootclasspath> 
    </configuration> 
    </plugin> 

Y ahora solo necesita hacer que la variable ${java.home} esté disponible para su mvn (a través de las propiedades del sistema -D oa través de antiguas variables de entorno, o puede ser realmente elegante y rellenarlo en un perfil java 6 en su configuración de usuario).

Ahora acaba de ejecutar su construcción y ir a tomar una cerveza fría mientras resopla distancia ...

---- ---- EDITAR

Una última cosa ... Incluyendo en rt.jar su bootclasspath es siempre se requiere, sin embargo, descubrí que se pueden necesitar más caso por caso. Tuve que incluir jce.jar (en el mismo directorio que rt.jar) porque mi aplicación estaba haciendo trabajo de cifrado.

---- EDIT 2 ----

para las muecas, yo lo probé la otra dirección. En lugar de correr experto con Java 7 compilar para Java 6, me encontré con la experta en Java 6 compilar para Java 7. El primer intento es bastante sencillo:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <version>2.5.1</version> 
    <configuration> 
     <source>1.7</source> 
     <target>1.7</target> 
     <fork>true</fork> 
     <verbose>true</verbose> 
     <compilerVersion>1.7</compilerVersion> 
     <executable>${JAVA_7_HOME}/bin/javac</executable> 
     <encoding>UTF-8</encoding> 
    </configuration> 
    </plugin> 

Básicamente, me puse mi <source> y <target> a 1,7, pero eso claramente no sería suficiente porque 6 no pueden compilar el código 7. Volviendo al plugin del compilador, en realidad hay an example page que describe lo que se debe hacer.A saber, necesita <fork> de un nuevo proceso usando java 7 <executable>. Entonces ahora creo que estoy listo. Es hora de encender la construcción ...

C:\Projects\my-project>mvn package 
... 
Caused by: java.lang.UnsupportedClassVersionError: mypackage.StupidTest : Unsup 
ported major.minor version 51.0 
... 
[INFO] ------------------------------------------------------------------------ 
[INFO] BUILD FAILURE 
[INFO] ------------------------------------------------------------------------ 

¿Qué demonios es UnsupportedClassVersionError? Una mirada más cercana nos dice que es el plugin maven-surefire que está fallando. Así que intento solo mvn compile y con seguridad obtengo un éxito ya que el plugin surefire nunca se activó. Así que corro mvn -X package y cuenta de esta joya:

Forking command line: cmd.exe /X /C ""C:\Program Files\Java\jdk1.6.0_29\jre\bin\ 
java" -jar C:\Projects\my-project\target\surefire\surefirebooter2373372991878002 
398.jar C:\Projects\my-project\target\surefire\surefire1861974777102399530tmp C: 
\Projects\my-project\target\surefire\surefire4120025668267754796tmp" 

Ok, por lo que su ejecución Java 6. ¿Por qué? La documentación para el éxito seguro da esto:

jvm: 
Option to specify the jvm (or path to the java executable) to use with the forking 
options. For the default, the jvm will be a new instance of the same VM as the one 
used to run Maven. JVM settings are not inherited from MAVEN_OPTS. 

Como nos encontramos con un mvn java 6 VM su bifurcar un java 6 VM para sus pruebas de unidad. Por lo que establecer esta opción apropiada:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-surefire-plugin</artifactId> 
    <version>2.12</version> 
    <configuration> 
     <jvm>${JAVA_7_HOME}/bin/java</jvm> 
    </configuration> 
    </plugin> 

Y encendiendo la acumulación ...

[INFO] ------------------------------------------------------------------------ 
[INFO] BUILD SUCCESS 
[INFO] ------------------------------------------------------------------------ 
+0

¿Ha cambiado algo con Java 8? Estoy construyendo con un objetivo de Java 6 y si configuro 'bootclasspath' en mi' pom.xml', obtengo el temido 'archivo de clase que tiene la versión incorrecta 52.0, debería ser 50.0'. Cuando elimino * 'compilerArguments' y solo guardo' source' y 'target', mi compilación no falla. Eso es exactamente lo contrario de esta respuesta. Más detalles en esta pregunta: http://stackoverflow.com/questions/34854961/class-file-has-wrong-version-after-jenkins-upgrade –

+0

@AmedeeVanGasse, lo siento, no tengo conocimiento de algo que podría causar Java 8 comportarse de manera diferente a la situación anterior. – Lucas

+0

No importa. Sospecho que hay una versión muy antigua del plugin de compilación Maven, porque funciona exactamente como en su ejemplo con la versión actual, 3.3 y los parámetros exactamente como en sus respuestas. Lo más peculiar, pero tales son las sutilezas de Maven. –

0

Sólo una nota, si una versión incorrecta es recogido, obtendrá un error como algo

xxxx is not supported in -source 1.5 
[ERROR] (use -source 7 or higher to enable yyyy) 

Durante la liberación de maven, maven libera el complemento (establece/por defecto a) el compilador versión 1.5. Para asegurarse de que recoge la versión correcta, especifique las propiedades.

<properties> 
<maven.compiler.source>1.7</maven.compiler.source> 
<maven.compiler.target>1.7</maven.compiler.target> 
</properties> 
Cuestiones relacionadas