6
votes

Java Input = "" n'est pas la même chose que l'entrée = null?

Je gère une application J2ME et je rencontre des problèmes de mémoire grave.
J'ai donc construit à une autre étape pour effacer la chaîne d'entrée énorme et traiter ses données et l'effacer. Mais cela n'a pas résolu le problème jusqu'à ce que je fixe INPUT = NULL ET PAS INPUT = "" . < p> ne devrait-il pas être la même chose en termes de gestion de la mémoire? Quelqu'un peut-il m'expliquer la différence s'il vous plaît?

merci,
Rayt xxx

EDIT:

Je veux toujours signaler une réponse comme solution. Je pense que les remarques mmyers vont dans la bonne direction.


3 commentaires

Je suppose que cela dépend de la fonctionnement du collecteur de poubelles J2ME, mais de la réaffectation entrée à n'importe quoi ( null , "" "" i Comme une pizza ") devrait permettre à GC récupérer la chaîne d'entrée énorme.


Voir aussi Stackoverflow.com/Questtions/473685/...


Désolé, je ne connais pas la réponse. Je sais juste une mauvaise réponse quand je le vois.


6 Réponses :


5
votes

entrée = null supprime (le collecteur de déchets supprime) l'objet en mémoire, tandis que entrée = "" instancie une chaîne objet La chaîne vide "" . En définissant l'entrée sur NULL, vous effectuez une entrée un objet vide, de sorte qu'il ne prendra pas aucune mémoire , tout en réglant entré = "", vous le réglez sur un nouvel objet, qui va certainement prendre certains la mémoire (évidemment, il devrait être minimal).

Vous pouvez consulter Cet article de IBM Parlez de Java GC et de la performance, qui décourage ma recommandation précédente. Il dit:

L'annulation explicite est simplement la pratique de définir des objets de référence à NULL quand vous avez fini avec eux. l'idée derrière l'annulation est que Il aide le collecteur des ordures par faire des objets inaccessibles plus tôt. Ou au moins c'est la théorie.

il y a un cas où l'utilisation de L'annulation explicite n'est pas seulement utile, mais pratiquement requis, et c'est où une référence à un objet est scopé plus largement qu'il n'est utilisé ou considéré comme valide par le programme Spécification. cela comprend les cas comme utiliser une statique ou une instance champ pour stocker une référence à un tampon temporaire, plutôt qu'un local variable, ou en utilisant un tableau pour stocker Références qui peuvent rester accessibles par le temps d'exécution mais pas par l'implicite Sémantique du programme.

et en outre,

Dans la colonne de septembre 1997 "Java Developer Connect Tech Tips" (voir Ressources), Soleil a averti de ce risque et a expliqué comment l'annulation explicite était nécessaire dans des cas comme l'exemple POP () ci-dessus. Malheureusement, les programmeurs prennent souvent ce conseil trop loin, en utilisant explicitement nulling dans l'espoir d'aider le collectionneur des ordures. Mais dans la plupart des cas, il n'aide pas le collecteur à ordures du tout , et dans certains cas, il peut en réalité blesser la performance de votre programme.


6 commentaires

Mais de toute façon, l'ancienne chaîne n'a pas de références, elle devrait donc être éligible à la collecte.


L'une quelconque change quelle entrée se réfère donc à ce qu'il aura le même effet du point de vue des collectionneurs à déchets.


Vous avez raison, le contenu original de l'entrée doit être supprimé dès que LISTXML et l'entrée ne vous y référent plus. Mais en définissant une entrée à NULL, vous sont raconter le GC le supprimer dès que possible.


Il n'y a rien de spécial à définir une variable de référence à NULL par rapport à une autre valeur. Ce n'est certainement pas un signal magique à GC pour "Supprimer le plus tôt possible".


@Voyager Où dit-il que la définition d'une variable pour NULL indique à la GC de "supprimer ceci dès que possible?" Je ne pense pas que ce soit vrai.


@ Kevin, Pavel: Je me suis trompé par un mauvais conseil que j'ai appris à l'université, que je suis heureux d'avoir corrigé.



5
votes

L'utilisation d'une stringbuffer pourrait être une meilleure approche

Une partie de celle-ci a déjà été répondue ici à SO:

Builder String et Stringbuffer à Java

Pourquoi utiliser Stringbuffer dans Java au lieu de l'opérateur de concerts de chaîne


3 commentaires

C'est en fait une solution bien meilleure.


Chaque fois que vous écrivez entrée + = bla () Un nouvel objet de chaîne est créé, tout le contenu de l'ancien obtenu est copié dans celui avec la sortie de bla () annexé, et l'ancienne entrée est marquée pour GC. C'est très lent et inefficace. Stringbuffer la résout.


L'efficacité n'est pas sa question ici. Il a une question sur la mise en œuvre sous-jacente de NULL par rapport à une chaîne vide. Donc, vous n'avez pas répondu à sa question. S'il avait posé des questions sur la performance, alors il serait bon de lui dire de profiler le code des goulots d'étranglement. Avait-il trouvé un problème causé par une concaténation de cordes copieuses, puis conseiller l'utilisation Stringbuffer serait une bonne réponse à cette question. Mais pourquoi lui dire comment optimiser quand vous ne savez pas qu'il a un problème de performance et ne lui demandait même pas?



12
votes

Chaque variable est en fait un pointeur sur "Data" en mémoire.

Entrée = "" attribue l'entrée à un objet de chaîne. Il a une longueur (0) et un tableau vide, ainsi que quelques autres pièces de données associées à celle-ci.

entrée.length () retournera 0 à ce stade.

entrée = null rend le point d'entrée sur "invalide". NULL est une sorte de cas particulier qui signifie que ce pointeur pointe de rien, il n'est pas affecté.

entrée.length () va maintenant lancer une exception parce que vous appelez .Longueur sur rien.


2 commentaires

donc 'null' peut consommer un peu moins de mémoire que "" mais les deux devraient être meilleurs que de grandes chaînes


Oui, mais je reçois un sentiment vraiment génial chaque fois que quiconque "vide" une variable. Celui de l'exemple doit être une variable de méthode et devrait donc disparaître la seconde la méthode. La définir à NULL ou "" "probablement simplement, car il est plus pour l'exécution d'optimiser. En d'autres termes, si l'entrée = NULL fait quelque chose de plus, cela signifie que l'entrée n'est pas suffisamment portée. Fixez-le en premier!



1
votes

dans les chaînes Java sont des objets et des noms de variables d'objet sont toujours des pointeurs. Si vous avez une chaîne appelée entrée et tapez entrées = null, cela pointe une entrée dans un espace null en mémoire. Si vous avez entré = "", il crée une chaîne qui ne contient aucun texte, une chaîne vide.


0 commentaires

2
votes

Je voudrais ajouter un peu à la réponse de Voyager:

Concernant les chaînes

L'énoncé entrée = ""; à partir d'un point de vue de la collection de déchets est identique à l'écriture entrée = "abcde ..."; , en ce que ni la déclaration ne nulifie la Instance d'objet entrée , mais les deux modifient simplement le contenu de la chaîne d'entrée variable. Aussi, pour la précision et la clarification, entré = quelque chose " modifie le contenu de entrée , tandis que String entrée =" "; instanciates INPUT .

Si l'entrée == "", alors "si (entrée.isempty ()) serait vrai, mais si (entrée == null)` serait faux.

Concernant la collecte des ordures

L'énoncé entrée = null; décrémente le nombre de références sur cet instance d'objet spécifique, qui, s'il s'agit de la dernière référence à entrée , alors entrée < / Code> sera marqué pour la collecte des ordures qui se passera non-déterminatinalement alias quand le collecteur des ordures qui lui rend. Un cas où entrée = null; ne serait pas réellement signalé entrée pour la collection de déchets serait: si entrée a également été transmis à une collection; Jusqu'à ce que entrée a été supprimé de la collection, il conserverait le nombre de références de décrémenter et donc d'être des déchets collectés.

J'espère que cela aide et à toute personne d'autre, n'hésitez pas à corriger les erreurs même si elles sont subtiles.

-bn


6 commentaires

entrée = "" est pas "modifie le contenu de la chaîne d'entrée variable"; Cela ne le réaffecte que la décrémentation du nombre de références sur la chaîne d'origine. Du point de vue de la chaîne d'origine originale, toute réaffectation de entrée décrémente le nombre de références et ne fait aucune différence pour savoir si la réaffectation est de " ", null ou " jon skeet ".


Je vois, vous dites que entrée = ""; ne signifie pas que l'ancienne valeur de entrée doit être marquée dans la phase "Mark" avant de pouvoir être collecté dans la phase "Balayer", tandis que entrée = null; le fait marquer, de sorte que vous n'avez besoin que d'attendre une phase "marque"?


@myers J'avais l'impression que Java's GC n'a pas conservé les comptes de référence, car avec GC générationnelle, cela prendrait plus de mémoire qu'il ne vaut la peine.


Il est important de se rappeler que les variables sont des références aux objets, pas d'objets eux-mêmes. Les objets de chaîne Java sont immuables - inchangables. Vous ne pouvez modifier que quelles références variables, pas l'objet de chaîne lui-même. @Imageist Oui, Java ne conserve pas les comptes de référence, il figure en fait si un objet est référencé par une variable en suivant le graphique de référence au moment de l'exécution.


Cela ne conserve pas les comptes de référence en soi , mais toute référence forte empêchera la GC de récupérer un objet.


MMYers, pourriez-vous s'il vous plaît élaborer le 24 juillet 19:34? Spécifiquement je suis curieux de la déclaration "en soi"; J'aimerais mieux comprendre le GC mieux (parlant de quoi, avez-vous une recommandation ou une source préférée d'aller sur le fonctionnement interne de la JVM, du GC, etc.)



3
votes

Plutôt que de spéculer sur la raison pour laquelle le collecteur des ordures ne collecterait pas votre objet, je préfère rassembler des preuves sur la situation. D'autres ont déjà posté leurs suppositions.

Si possible, créez des fichiers de décharge de tas pour observer la mémoire dans votre JVM lorsqu'il exécute votre code, puis inspectez-les pour voir quels objets y existe.

Voici une page Web qui vous dit comment faire cela: http://twit88.com/blog/2008/12 / 19 / Java-Dépannage-Memory-Problème /

bonne chance!


Une autre idée: écrivez un programme court qui ne fait rien de plus que de créer de gros objets de chaîne, puis d'allumer le mode de collecte des ordures verbeux, pour voir ce qui se passe là-bas. Si vous pouvez reproduire le comportement dans un petit programme, vous pouvez l'étudier plus facilement. Je pense que vous pouvez constater que la JVM sur un PC peut se comporter différemment de la JVM dans un appareil J2ME comme un téléphone portable.


1 commentaires

La raison pour laquelle je ne peux pas répondre à cette question est, je ne m'attendrais pas à ce que Java se comporte de cette façon. Il ne devrait faire aucune différence entre S = NULL ou S = "". Rayt a déclaré qu'il faisait une différence, il doit donc y avoir une lacune dans ma compréhension. J'apprends mieux en lisant des informations provenant de sources autoritaires (Sun et IBM sont bonnes) et d'expérimentation directe.