web-dev-qa-db-fra.com

options javac source et cible

J'ai vu les options de compilation telles que discutées dans Quelles distributions du JDK peuvent exécuter `javac -source 1.6 -target 1.5`? . Je comprends les options individuelles pour la source et la cible. Je ne comprends pas pourquoi la version source est supérieure à la version cible. Compiler le code pour les anciennes cibles est logique. Mais dans ce cas, pourquoi ne pas simplement utiliser -source de la plus ancienne cible sur laquelle nous voulons pouvoir fonctionner

24
jogabonito

Java est rétrocompatible. Vous utilisez l'option -source pour spécifier la version Java utilisée pour la compilation et l'option -target pour spécifier la version Java la plus basse à prendre en charge. par exemple. Si je spécifie une cible de 1,4, mon programme ne pourra pas s'exécuter sur Java 1.3 ou une version inférieure. voir la documentation javac suivante pour plus d’informations. en particulier la section sur Options de compilation croisée

21
greenkode
  • source: la version que votre code source nécessite de compiler.
  • cible: version la plus ancienne de JRE que vous souhaitez prendre en charge.

Assurez-vous également de définir bootclasspath pour vous assurer que votre programme fonctionnera sur les anciennes machines virtuelles.


De la javacdocumentation :

Exemple de compilation croisée

L'exemple suivant utilise javac pour compiler le code qui s'exécutera sur une machine virtuelle 1.6.

C\:>javac -source 1.6 -target 1.6 -bootclasspath C:\jdk1.6.0\lib\rt.jar -extdirs "" OldCode.Java

L'option -source 1.6 spécifie que la version 1.6 (ou 6) du langage de programmation Java doit être utilisée pour compiler OldCode.Java. L'option -target 1.6 assure que les fichiers de classe générés seront compatibles avec les 1.6 ordinateurs virtuels. Notez que dans la plupart des cas, la valeur de l'option -target est la valeur de l'option -source; dans cet exemple, vous pouvez omettre l'option -target.

Vous devez spécifier l'option -bootclasspath pour spécifier la version correcte des classes d'amorçage (la bibliothèque rt.jar). Sinon, le compilateur génère l'avertissement suivant:

C:\>javac -source 1.6 OldCode.Java
warning: [options] bootstrap class path not set in conjunction with -source 1.6

Si vous ne spécifiez pas la version correcte des classes de démarrage, le compilateur utilisera les anciennes règles de langage (dans cet exemple, il utilisera la version 1.6 du langage de programmation Java) associé aux nouvelles classes de démarrage, ce qui peut entraîner ne fonctionnent pas sur l'ancienne plate-forme (dans ce cas, Java SE 6), car la référence à des méthodes inexistantes peut être incluse.

21
Peter Tseng

Peter Tseng mentionne beaucoup de points clés à retenir lors de la compilation. En fait, j’ai déjà été confronté à un problème similaire il ya un certain temps et j’aimerais en partager les causes profondes.

J'avais un code source qui devait compiler et le rendre compatible (-source & -target) Java '1.8' . Le code lui-même avait 

  1. Beaucoup de symbole de marque déposée, donc je me suis retrouvé dans des caractères non reconnus (je devais modifier les paramètres d'encodage de l'IntelliJ Idea)
  2. Beaucoup de modifications apportées au package Java.sql.*
  3. Utilisation de nombreuses bibliothèques tierces. Épargnez-moi l'horreur d'expliquer la difficulté à déboguer là-bas et bla bla bla.

Après certaines modifications, je me suis retrouvé avec un code qui avait le même nombre de tests JUnit à exécuter. Finalement, je suis tombé sur un Java.lang.VerifyError. J'ai été choqué quand j'ai compris qu'une telle erreur se produisait lorsque je compilais et exécutais le code dans différentes bibliothèques/environnements (ce qui n'était pas le cas).

Ce qui m'a presque manqué, c'est que, pour avoir honoré le fait que les tests devaient être exécutés dans un environnement isolé, le Junit et ses tests étaient exécutés de manière séparée VM

<target name="runJunit">
    <junit printonsummary="on" 
           haltonfailure="off"
           fork="true"
           forkmode="once">
        <formatter />
        <batchtest />
        <classpath />
    </junit>
</target>

Cela fera évidemment l'objet d'un processus séparé et agira comme une application autonome en exécution. Même si IDE couvre les deux processus de manière synchrone, les machines virtuelles sont assez isolées. 

Après Java 1.7, Oracle a introduit une vérification plus stricte et modifié un peu le format de la classe - afin de contenir une mappe de pile, utilisée pour vérifier que le code est correct . L'exception que j'ai vue est due au fait qu'une méthode n'a pas de mappage de pile valide. J'ai finalement essayé d'inclure de nombreuses options JVM pour modifier le paramètre, mais en vain.

<jvmarg value="bootclasspath:{env.Java_HOME}\jre\bin\rt.jar" prefix="-X"/>

rien n'a fonctionné. Le seul travail autour était d'inclure 

<jvmarg value=":UseSplitVerifier" prefix="-XX"/>

En Java 1.7, autoriser uniquement la vérification du code d'octet nominal. Depuis que cela a été fait avec Java 1.8, la seule option était d’utiliser

<jvmarg value="-noverify"/>
2
Nitin Ramac

JDK1.8 ne prend plus en charge -source et -target inférieur à 1,6

"c:\Program Files\Java\jdk1.8.0_121\bin\javac.exe" -source 1.3 HelloWorld.Java
warning: [options] bootstrap class path not set in conjunction with -source 1.3
warning: [options] source value 1.3 is obsolete and will be removed in a future release
warning: [options] target value 1.4 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
4 warnings
0
hfmanson