Je peux voir ce comportement curieux du collecteur des ordures si je passe au débogage et que je pose un point d'arrêt sur // 1 foo n'est pas null et sa valeur est "bar" mais dans Point d'arrêt // 2 FOO est null, cela peut être difficile à comprendre pendant que vous êtes débogué. Ma question est de savoir s'il existe des spécifications qui indiquent qu'il s'agit d'un comportement juridique du collecteur des ordures p> avec cette petite variation, il ne reçoit pas la poubelle collectée: P> public class A {
public static void main(String[] args) {
String foo;
try {
foo = "bar";
} catch (Exception e) {
throw new RuntimeException(e);
}
int foobar = 3;
}
}
4 Réponses :
Dans ce cas, vous n'utilisez pas la variable FOO après la définition, il serait donc légal que le JVM ignore complètement la variable car il n'est jamais utilisé et cela ne changerait pas le résultat de votre programme. < p> Cependant, il est peu probable que cela se produise dans le mode de débogage. P>
Dans votre cas, FOO ne doit pas obtenir de GC'ed tant qu'il est en portée ou que vous vous en tenez une référence, qui inclut la section après la Essayez / Catch Block. P>
EDIT FORT> P> En fait, je reçois le même comportement que ce que vous décrivez dans NetBeans 7.1.1 avec Java 7.0_03 ... < / p> Un problème peut être que parce que vous ne définissez pas une valeur par défaut sur bytcode strong> p> Je ne suis pas un spécialiste de bytcode, mais ils ont l'air très similaire à celui-ci ... p> conclusion forte> p > ma conclusion personnelle est que pour le débogueur de montrer la valeur de pour convaincre que cela n'a rien à voir avec GC, vous pouvez essayer l'exemple suivant: < / p> sur la ligne même plus drôle exemple: p> sur le foo code>, vous ne pouvez pas l'utiliser après le bloc d'essai / attraper (il ne compilerait pas). < / p>
string foo = null; code> comme première instruction, auquel cas le débogueur voir la valeur après le bloc Type / Catch: Li>
ul> foo code>, il doit exécuter un foo.tostring () code> d'une certaine sorte, ce qui n'est pas Une instruction valide après le bloc de capture comme FOO code> n'aurait peut-être pas été initialisée. Ajouter un system.out.println (foo) code> dans cette section n'est pas légal (ne compile pas). Le débogueur est un peu perdu quant à ce que la valeur est et montre null code>. P> foobar code>, vous pouvez voir que c code> contient la barre code> mais foo shows comme null code>. Donc, la chaîne est toujours là, mais le débogueur ne peut pas le montrer. P> foobar Code> ligne, foo code> Affiche comme null code>, mais list code> contient "bar" code> ... sympa. p> p>
Oui c'est vrai si je définis foo code> sur NULL avant le bloc d'essai, il ne reçoit pas GC'ed, mais comme vous l'avez dit en mode de débogage, je l'ai même besoin.
@jaime no gc n'est jamais exécuté dans ce programme. Ce n'est qu'une question de savoir ce que le débogueur nous montre, les informations sont disponibles dans les deux cas.
foo code> n'a jamais de valeur par défaut et lorsque vous allez à la ligne 2, vous passez en dehors de la portée dans laquelle il a été défini. p>
Juste, mais je veux juste le déboguer: * (
Si cela est vrai, n'est-ce pas un comportement très dangereux?
Ce n'est pas un comportement juridique, car le contexte de la méthode principale est toujours en vie. Il ne devrait idéalement pas être gisé que si vous déclarez la chaîne foo dans le bloc d'essai (auquel cas ne sera pas accessible à 2). P>
J'ai essayé ce code et ça va bien pour moi. P>
Tort. Tant que le comportement ne peut être vu du thread d'exécution (il ne peut évidemment pas), il est parfaitement valide pour écraser la valeur, le gc ou autre chose.
Je doute toujours. GC ne peut pas collecter la valeur car il est très possible et utilisé.
Comportement juridique mais obscurément et déroutant à des fins de débogage
Wow, j'ai besoin de rechercher cela plus. Je vais proposer une explication bientôt.
@Sidcool La règle comme-si elle fait preuve d'autre chose. Une analyse de la vie rapide peut facilement montrer que la variable est morte à ce stade, vous pouvez donc l'écraser, le gc ou quoi que ce soit. Aucun programme juridique ne remarquera jamais la différence.
Le code octet généré est comme suit:
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String bar
2: astore_1
3: iconst_5
4: istore_2
5: goto 9
8: astore_2
9: iconst_3
10: istore_2
11: return
Exception table:
from to target type
0 5 8 Class java/lang/Exception
Consultez ma mise à jour - je ne vois aucune différence avec le bytecode généré lorsque la nourriture est initialement définie sur NULL.
@assylie Eh bien, vous voyez une différence dans le bytecode, mais seulement les attentes. Rien de sortir de l'ordinaire oui.
Quel débogueur utilisez-vous?
Quel débogueur utilisez-vous? Ce comportement semble improbable.
Que se passe-t-il si vous ajoutez
system.out.println (foo); code> après leint foobar = 3; code> assignation mais laissez le point d'arrêt au même endroit?Je pense que c'est parce que
foo code> n'a pas de valeur initiale.Je pense que c'est un hapening parce que vous n'utilisez plus FOO plus à // 2 et après. Essayez de mettre un système.out.print (FOO) après // 2 et exécutez à nouveau le débogage.
@Louiswasserman Je reçois en fait le même comportement ...
Même comportement dans Intellij aussi. Voyons ce que le bytecode est.
En réponse à «Si ce n'est plus utilisé à ce stade, comment cela affecterait-il le débogage à ce moment-là?»: Parce que je recherchais une nouvelle API débogage de ses méthodes / rendements
En réponse à "Que se passe-t-il si vous ajoutez System.Out.println (FOO); après l'int Foobar = 3; mission mais laissez le point d'arrêt au même endroit?": Dans ce cas, "FOO 'existe comme prévu, il n'arrive que S'il n'est plus référencé
Quel débogueur? Pas sûr de simplement déboguer Oracle JDK JDK1.6.0_25 de Intellij Idea
Strange j'ai supposé que Javac réutiliserait la tache de variable locale (c'est-à-dire attribuer à la fois FOO et FOOBAR à la variable locale 1), mais cela ne fait pas cela. C'est à dire. La valeur est toujours disponible et non écrasée.
@jaime Votre édition le rend encore plus étrange - bien fait ;-)
Hahah Mais votre dernière réponse a du sens, une exception étant jetée d'un bloc de capture dire implicitement que vous pouvez appeler des méthodes "foo" (c'est-à-dire une totring ()) après le bloc de capture, car il n'y a qu'un seul chemin d'exécution.
@jaime Oui Vous avez raison, avec cette exception supplémentaire
foo.tostring () code> devient une instruction valide après le bloc de capture.Oui, merci de toute façon, je doute toujours sur la raison pour laquelle le débogueur a les mêmes limitations que l'environnement d'exécution normal où cet appel (Tostring ()) est illégal après le bloc de capture
@jaime n'est pas sûr non plus. J'ai ajouté un autre exemple qui est drôle ;-)