2009-08-13 5 views
0

Y a-t-il une raison évidente pour laquelle un programme Java exécuté à partir de la sortie de l'IDE Eclipse est différent de ce que je reçois si je fais la même chose avec Windows (XP)? J'utilise le JDK 1.6.0_04 et Eclipse 3.4.0La sortie Java d'Eclipse et de Command Line diffère

Le programme crée des threads, puis teste un algorithme de verrouillage. Dans Eclipse, les threads n'interfèrent pas les uns avec les autres. Cependant, en utilisant javac, les threads s'interrompent les uns les autres.

+4

S'il vous plaît fournir plus d'informations: Comment exactement "différent"? –

+0

peut être beaucoup de choses, différentes JVM, débogage affectant les sorties de threads, différents paramètres de journaux et/ou niveaux de journaux –

Répondre

2

Une chose qui pourrait être la cause d'un comportement différent est, si vous avez par exemple. deux pots qui fournissent la même fonctionnalité (deux versions du même pot). Selon la manière dont vous spécifiez le chemin de classe, le code d'un fichier jar peut remplacer l'autre. Maintenant, dans eclipse, l'ordre peut être différent de celui de la ligne de commande. Vous appelez donc du code différent, ce qui entraîne une sortie différente.

+0

Garder les informations de chemin de classe générées par Eclipse semble être le chemin à parcourir. – pypmannetjies

2

Si vous jouez avec des threads, la sortie de la console peut varier énormément d'une machine à l'autre, et je suis sûr que eclipse fait quelque chose pour affecter le thread d'une manière ou d'une autre.

1

J'avais l'impression que Eclipse avait son propre compilateur intégré (et une recherche Google confirme que j'ai raison). Il peut y avoir des différences mineures dans sa compilation par rapport à javac.

0

Oui, peut-être que Eclipse a activé une option JAVA comme la récupération de place prolixe ou quelque chose comme ça. Vous pouvez généralement vous connecter à la JVM en utilisant [jre] /bin/Jconsole.exe pour voir ce qui est activé sur la JVM, puis vous pouvez comparer. Cela vous montrera des différences dans le classpath ainsi que d'autres choses. Pour faire ce travail, vous devez ajouter cela comme une option de démarrage à la machine virtuelle Java que vous voulez inspecter:
-Dcom.sun.management.jmxremote

0

Êtes-vous sûr synchronisé les fils correctement, le cas échéant?

Les unités d'exécution sont-elles dépendantes les unes des autres? Si oui, c'est une raison probable de la différence de comportement.

Essayez d'analyser votre programme. Le programme fonctionnerait-il si le thread 1 finissait bien plus vite que le thread 2? Le programme fonctionnerait-il si le thread 2 finissait bien plus vite que le thread 1?

Si par exemple le thread 1 génère un résultat qui sera utilisé ultérieurement par le thread 2. Est-il possible de garantir que le thread 2 n'essaie pas d'utiliser ce résultat avant qu'il ne soit généré? (Permet de dire que le fil 2 fonctionne très vite)

En résumé: Différents temps d'exécution relatifs pourraient être la raison de la différence de comportement, si le programme est mal synchronisé

0

Je suppose que vous dites le " Les threads s'interrompent "Vous voulez dire que la sortie des deux threads est intercalée. J'imagine aussi que vous écrivez à System.err ou System.out.

Je crois que ce que vous voyez est une conséquence de deux threads effectuant une sortie non synchronisée vers le même flux. Dans Eclipse, le flux dans lequel vous écrivez a suffisamment de mémoire tampon pour qu'un appel à write() ne se bloque pas (99,9% du temps). En revanche, lorsque vous exécutez à partir de la ligne de commande, il est tout à fait possible que chaque appel Java write() entraîne un appel système en écriture, bloquant un thread et ordonnant l'autre. En effet, il est même possible qu'un Java write() puisse se transformer en plusieurs appels système en écriture!

La réponse simple serait d'essayer de changer la mise en mémoire tampon pour votre flux. Malheureusement, je ne pense pas que les API Java vous permettent de faire cela pour les flux de sortie/erreur standard de la console.

D'autres réponses imparfaites comprennent:

  • Changer votre application pour synchroniser toutes vos écritures sur l'objet System.out/err. Malheureusement, cela risque de masquer les bogues de synchronisation dans le code que vous essayez de tester !!

  • Modifiez votre application pour la sortie vers un ByteArrayOutputStream(). Cela permettra de réduire le changement de "interruption", mais il pourrait encore arriver de temps en temps, sauf si vous synchronisez.

La meilleure réponse que je peux penser est de créer une classe wrapper flux/Reader qui synchronise écrit à un ByteArrayOutputStream, écrire tous les messages à une instance, puis vider le lot à System.out (ou ailleurs) quand le test est terminé. Cela peut masquer les bogues de synchronisation, mais il est beaucoup moins probable que si vous synchronisé sur les objets System.out/err.