Question

J’essaie de compiler plus de 100 classes java à partir de différents paquets à partir d’un (pas de compilations incrémentielles) à l’aide des tâches ANT suivantes :

<target name="-main-src-depend">
    <depend srcdir="${src.dir}" 
            destdir="${bin.dir}" 
            cache="${cache.dir}"
            closure="true"/>
</target>   

<target name="compile" depends="-main-src-depend"
        description="Compiles the project.">

    <echo>Compiling</echo>

    <javac  target="${javac.target}"
            source="${javac.source}"
            debug="${javac.debug}"
            srcdir="${src.dir}"
            destdir="${bin.dir}">
        <classpath>
            <path refid="runtime.classpath"/>
            <path refid="compile.classpath"/>
        </classpath>
    </javac>
</target>

Cependant, la première fois que j'exécute la tâche de compilation, j'obtiens toujours une StackOverflowException.Si je réexécute la tâche, le compilateur effectue une construction incrémentielle et tout fonctionne correctement.Ceci n'est pas souhaitable puisque nous utilisons Régulateur de vitesse faire une construction quotidienne automatique, ce qui provoque de faux échecs de construction.

En tant que solution rapide et simple, j'ai créé 2 tâches distinctes, compilant des parties du projet dans chacune.Je ne pense vraiment pas que cette solution tiendra à mesure que d'autres classes seront ajoutées à l'avenir, et je ne veux pas ajouter de nouvelles tâches de compilation à chaque fois que nous atteignons la "limite de compilation".

Était-ce utile?

La solution

Ce sera bon à savoir ;Qu’est-ce qui peut provoquer ou provoque une erreur StackOverflowError lors de la compilation du code Java ?

Il est probable que l'évaluation de l'expression longue dans votre fichier Java consomme beaucoup de mémoire et, comme cela est effectué conjointement avec la compilation d'autres classes, la machine virtuelle manque tout simplement d'espace de pile.Votre classe générée repousse peut-être les limites légales de son contenu.Voir chapitre 4.10 Limites de la machine virtuelle Java dans Spécification de la machine virtuelle Java, deuxième édition.

Correctif 1 :refactoriser la classe

Puisque votre classe est en cours de génération, cela n’est peut-être pas une option.Néanmoins, cela vaut la peine d'examiner les options proposées par votre outil de génération de classes pour voir s'il peut produire quelque chose de moins gênant.

Correctif 2 :augmenter la taille de la pile

Je pense Kieron a une solution lorsqu'il mentionne l'argument -Xss. javac prend un certain nombre d'arguments non standard qui varient selon les versions et les fournisseurs de compilateurs.

Mon compilateur :

$ javac -version
javac 1.6.0_05

Pour lister toutes les options, j'utiliserais ces commandes :

javac -help
javac -X
javac -J-X

je pense la limite de pile pour javac est de 512 Ko par défaut.Vous pouvez augmenter la taille de la pile de ce compilateur à 10 Mo avec cette commande :

javac -J-Xss10M Foo.java

Vous pourrez peut-être transmettre cela dans un fichier Ant avec un compilateur élément imbriqué dans votre javac tâche.

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J-Xss10M" />
</javac>

Autres conseils

  <javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
      <compilerarg value="-J-Xss10M" />
    </javac>

du commentaire ci-dessus est incorrect.Vous avez besoin d'un espace entre -J et -X, comme ceci :

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J -Xss10M" />
</javac>

pour éviter l'erreur suivante :

 [javac] 
[javac] The ' characters around the executable and arguments are
[javac] not part of the command.
[javac] Files to be compiled:

...[javac]javac :drapeau invalide :-J-Xss1m [Javac] Usage:javac

Essayez d'ajouter une variation de ces attributs au Fourmi javac tâche doubler:

memoryinitialsize="256M" memorymaximumsize="1024M"

Vous pouvez également essayer fork="true", je ne sais pas si cela vous permet de définir des valeurs pour la pile et le tas (alias -Xm1024), mais cela peut aider (si cela fonctionne à partir de la ligne de commande, mais pas dans Ant).

[Modifier]:Lien ajouté -- le javac tâche La page semble suggérer que les paramètres ci-dessus nécessitent que vous définissiez également fork="true".

Cela se produit-il lorsque vous exécutez la commande javac à partir de la ligne de commande ?Vous voudrez peut-être essayer le fourchette attribut.

C'est assez étrange, 100 cours, ce n'est vraiment pas tant que ça.Que fait le compilateur lorsque la pile déborde ?Existe-t-il une trace de pile utile générée ?Que se passe-t-il si vous courez javac directement sur la ligne de commande au lieu de passer par Ant ?

Une solution possible consiste simplement à augmenter la taille de la pile à l'aide de l'option -Xss argument à la JVM ;soit à la JVM en cours d'exécution ant ou en définissant fork="true" et un <compilerarg> sur le <javac> tâche.En fait, maintenant que j'y pense, le problème disparaît-il simplement en mettant le fork="true"?

Voici ce que j'ai trouvé.Après avoir posté ma question, j'ai continué et modifié la tâche de compilation avec les attributs fork="true", memoryinitialsize="256m" et memorymaximumsize="1024m" (j'ai découvert aujourd'hui que cela avait été suggéré par Kieron et jmanning2k, merci pour votre temps).Cela n'a néanmoins pas résolu le problème.

J'ai décidé de commencer à supprimer des classes de l'arborescence source pour voir si cela pouvait identifier le problème.Il s'avère que nous avions une classe client de service Web pour Axe 1.4 qui a été généré automatiquement à partir d'un fichier WSDL.Maintenant, cette classe est un monstre (comme dans Frankenstein), elle a 167 membres de champ (tous de type String), 167 paires getter/setter (1 pour chaque champ), un constructeur qui reçoit les 167 champs en paramètres, un méthode égale qui compare les 167 champs d'une manière étrange.Pour chaque champ, la comparaison se déroule comme suit :

(this.A == null && other.getA() == null) || (this.A != null && this.A.equals(other.getA()))

Le résultat de cette comparaison est « anded » (&&) avec le résultat de la comparaison du champ suivant, et ainsi de suite.La classe continue avec une méthode hashCode qui utilise également tous les champs, certaines méthodes de sérialisation XML personnalisées et une méthode qui renvoie un objet de métadonnées spécifique à Axis qui décrit la classe et qui utilise également tous les membres du champ.

Cette classe n'est jamais modifiée, j'ai donc simplement mis une version compilée dans le chemin de classe de l'application et le projet a été compilé sans problème.

Maintenant, je sais que la suppression de ce fichier source unique a résolu le problème.Cependant, je n'ai absolument aucune idée de la raison pour laquelle cette classe particulière a causé le problème.Ce sera bon à savoir ;qu'est-ce qui peut provoquer ou provoquer une StackOverflowError lors de la compilation du code Java ?Je pense que je vais poster cette question.

Pour ceux que ça intéresse :

  • Windows XP SP2
  • JDK de SUN 1.4.2_17
  • Fourmi 1.7.0
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top