Effiziente Stringverarbeitung

Hi,

...
IMHO ist mccaes Aussage korrekt, dass sämtliche Strings im Constant Pool der JVM abgelegt werden. Du hast insofern recht, dass ein mit new String("blablubb") erzeugtes Objekt vom GC eingesammelt wird. Das zugehörige Literal "blablubb" jedoch bleibt im Pool, genau wie alle anderen erzeugten Strings. Nimm z.B....
und ich bleibe dabei, dass das Quatsch ist. Nur Literale, also Strings die zur Compilezeit vom Compiler aufgelöst werden können, gehen in den Pool, sowie Strings, auf denen zur Laufzeit intern() aufgerufen wird. String die erst zur Laufzeit aufgelöst werden können, gehen nicht in den Pool.

Sowohl dein, als auch (shame on me) mein Beispiel benutzen Literale - die gehen in den Pool. Wenn aber ein z.B.
Code:
 String str = reader.readLine();
aufgerufen wird, kann der vom Reader gelieferte String nicht zur Compilezeit aufgelöst werden und geht mit Sicherheit nicht in den Pool. Sobald keine Referenz auf diesen String zeigt, kann er von der GC abgeräumt werden.

Dies hat natürlich zur Folge, dass sämtliche nicht mehr verwendete bzw. referenzierte Strings (gerade bei so großen Strings, von denen hier die Rede war) unnötig Resourcen verbrauchen.
Wie gesagt, wenn es stimmen würde, dass alle Strings im Speicher bleiben, würden viele Java Anwendungen mit OutOfMemory abrauchen.

Gruß
THMD
 
Der StringPool wird wie von THMD schon erwähnt nur für literals (also alles was wie String s = ""; aussieht) und für Methoden und Klassennamen verwendet oder wenn man die JVM mit der intern() Methode dazu anweist.
 
Huhu,

Wie auch immer, FAKT ist, dass diese Operation je nach PC > 100 mal in der Minute ausgeführt wird und nicht am RAM Riegel lutscht, sondern dran knabbert wie ein Hamster.

Nach einem Test mit 1463 Durchläufen hat sich das Tool an Platz eins der Speicherverbrauchsliste im Windows TaskManager gefressen. (Mit knapp 42 Mb).

Das ist inakzeptabel.

Wenn ich jetzt mehr als 10000 Durchläufe machen würde, könnte das ganze absemmeln, da meiner Ansicht nach der Speicherverbrauch direkt Proportianal zu den Durchläufen steigt. (Habe ich beobachtet).

Gibt es nicht eine Möglichkeit Java zu zwingen nach jedem Durchlauf aufzuräumen?

Wenn nämlich keine Durchläufe gemacht werden, sinkt der allocated memory nicht, wieder auf Anfangsniveu.

Ich will jetzt nicht mit dem Finger auf den GarbageCollector zeigen, denn es könnte ja sein, dass ich auch schlampig gearbeitet habe,...

Die StringBuilder die ich erstelle... Was passiert mit denen?

Bei jedem Schleifendurchlauf wird in der Schleife ein neuer Stringbuilder ungefähr so erstellt:

StringBuilder njamnjamnjam = new StringBuilder("Website Website njam njam njam");

Irgendjemand hat mir eingeredet, ich muss die Referenz auf null setzen,...
Stimmt das?

Wird bei in Schleifen definierten Objekten, die ja nach der Schleife nicht mehr accessible sind nicht automatisch abgeräumt?

Wo sind denn die guten alten Pointer, die besten Freunde des Menschen (noch vor dem Hund) :p?
 
Hallo,
... Es geht um folgendes: Es ist eine Website auszulesen und der Quellcode zu analysieren. Es soll nach einem speziellen Tag gesucht werden und der Text zwischen Anfangs- und Endtag geholt werden....

...
Wie auch immer, FAKT ist, dass diese Operation je nach PC > 100 mal in der Minute ausgeführt wird und nicht am RAM Riegel lutscht, sondern dran knabbert wie ein Hamster.

also langsam interessierts mich doch - wozu muss man über hundert mal pro Minute eine Webseite auslesen, um einen Wert zwischen zwei Tags zu holen:confused:

...
Nach einem Test mit 1463 Durchläufen hat sich das Tool an Platz eins der Speicherverbrauchsliste im Windows TaskManager gefressen. (Mit knapp 42 Mb).

Das ist inakzeptabel.

Wenn ich jetzt mehr als 10000 Durchläufe machen würde, könnte das ganze absemmeln, da meiner Ansicht nach der Speicherverbrauch direkt Proportianal zu den Durchläufen steigt. (Habe ich beobachtet).
Dann begrenz doch den Speicher den die VM belegen darf entsprechend deiner Schmerzgrenze. Und dann probier es durch, ob sie wirklich aussteigt, oder stabil bleibt. Vielleicht ist Java auch nicht das Mittel der Wahl für die Aufgabe, vielleicht wärst du mit nem einfachen Skript besser dran?

Gibt es nicht eine Möglichkeit Java zu zwingen nach jedem Durchlauf aufzuräumen?
Nein, keine garantierte (bei SUN VM's). Du kannst dem Garbage Collector mit System.gc() einen Hinweis geben, dass er laufen soll, aber das ist wie gesagt nur ein Hinweis - er muss es nicht machen, außerdem stößt du damit immer eine Major Collection an.


Die StringBuilder die ich erstelle... Was passiert mit denen?
Wenn keine Referenz bzw. Softreferenz mehr auf sie zeigt, sind sie reif für die Garbage Collection und werden dann irgendwann abgeräumt.


Gruß THMD
 
Huhu,
Danke erstmal für die Antwort.

also langsam interessierts mich doch - wozu muss man über hundert mal pro Minute eine Webseite auslesen, um einen Wert zwischen zwei Tags zu holen:confused

Verschiedene URLs (POST/GET params) = Verschiedene Werte.
Es geht darum nach verschiedenen Texten zu crawlen die auf der Website liegen.

Durschnittlich werden hintereinander, je nach User an die 200 queries gemacht.
Es gibt aber auch ausnahmen,...

Dann begrenz doch den Speicher den die VM belegen darf entsprechend deiner Schmerzgrenze. Und dann probier es durch, ob sie wirklich aussteigt, oder stabil bleibt. Vielleicht ist Java auch nicht das Mittel der Wahl für die Aufgabe, vielleicht wärst du mit nem einfachen Skript besser dran?

Ja wie denn?
Ich trau mich ja nicht an die Settings wie Initial Heap Size, Maximum Allocated memory usw.

Ich weiß nicht was da optimal wäre...

Nein, keine garantierte (bei SUN VM's). Du kannst dem Garbage Collector mit System.gc() einen Hinweis geben, dass er laufen soll, aber das ist wie gesagt nur ein Hinweis - er muss es nicht machen, außerdem stößt du damit immer eine Major Collection an.

Ist das so ein Hinweis wie:

"Mach dich an die Arbeit du fauler Sack!",

"Bitte schau mal nach den Objekten",

oder eher wie eine Nachricht auf dem "Anrufbeantworter des GCs" wie:
"Hey Kumpel, ich hab ne Ladung Objekte die ich nicht brauche, wenn du wieder da bist, könntest du nach ihnen sehen?"

Wenn keine Referenz bzw. Softreferenz mehr auf sie zeigt, sind sie reif für die Garbage Collection und werden dann irgendwann abgeräumt.

Kann ich das ganze beschleunigen wenn ich manuell auf null setze?

Grüße,
Martin Conrad Caesar
 
Code:
 String str = reader.readLine();
aufgerufen wird, kann der vom Reader gelieferte String nicht zur Compilezeit aufgelöst werden und geht mit Sicherheit nicht in den Pool. Sobald keine Referenz auf diesen String zeigt, kann er von der GC abgeräumt werden.

Hmm... Okay. Wieder was gelernt.
Moment acker ich das Buch zum SCJP 6 durch, da stand, dass wirklich alle Strings im Pool landen. Aber vermutlich sind sie nur auf den für das Examen wichtigen Teil eingegangen.

Dann entschuldige ich mich für Fehlinformationen!
 
Zuletzt bearbeitet:
Hmm... Okay. Wieder was gelernt.
Moment acker ich das Buch zum SCJP 6 durch, da stand, dass wirklich alle Strings im Pool landen. Aber vermutlich sind sie nur auf den für das Examen wichtigen Teil eingegangen.

Ich habs genau so wie du es zuerst gesagt hast, in der Schule gelernt.
Die Lehrer kommen von ausserhalb (Firmen wie Siemens, usw.) und sollten sich ja auskennen,...
 
Ich habs genau so wie du es zuerst gesagt hast, in der Schule gelernt.
Die Lehrer kommen von ausserhalb (Firmen wie Siemens, usw.) und sollten sich ja auskennen,...
Ja... Die Autoren des SCJP 6 Buches sind Mitentwickler bei Sun (gewesen?) und da denkt man schon auch, dass Informationen vollständig sein sollten.

Und zum Topic:
Den GC kannst du wirklich nur höflich bitten, irgendwann in möglichst naher Zukunft doch mal aufzuräumen, mehr kannst du nicht machen. Referenzen auf null zu setzen beschleunigt zwar nichts, aber das Objekt wird natürlich erst dann aufgeräumt, wenn keine Referenz mehr dazu besteht. Insofern - schaden kann es wohl nicht :)
 
Hallo,

Ja... Die Autoren des SCJP 6 Buches sind Mitentwickler bei Sun (gewesen?) und da denkt man schon auch, dass Informationen vollständig sein sollten.

also wenn du das Sierra/Bates Buch meinst - ich hab zwar nur die SCJP 5 Variante (die nicht wirklich viel anders ist) und da reden sie über String Literale und für die trifft es ja auch zu, aber nicht alle Strings werden über Literale erzeugt.

Gruß
THMD
 
also wenn du das Sierra/Bates Buch meinst - ich hab zwar nur die SCJP 5 Variante (die nicht wirklich viel anders ist) und da reden sie über String Literale und für die trifft es ja auch zu, aber nicht alle Strings werden über Literale erzeugt.
Ja, dieses Buch meine ich. Version SCJP 6 unterscheidet sich schon in ein paar Dingen vom 5er, aber natürlich nicht in der String-Verarbeitung.

Und ich hab schon verstanden, was du vorher gemeint hast bezüglich des Pools. Mir war nur nicht klar, dass überhaupt ein String erzeugt werden kann, ohne dass ein Literal dazu im Speicher gehalten und damit im Pool abgelegt wird.
Da kreide ich dem Buch an, dass es zwar über Literale spricht, ohne jedoch auf Alternativen (wie Streams o.Ä.) hinzuweisen. Das meinte ich mit mangelnder Vollständigkeit.

Mir war kaum etwas zu Strings bekannt, obwohl ich schon mehrere Jahre professionell mit Java entwickle. Deshalb habe ich mich gefreut, durch den SCJP endlich Wissen diesbezüglich zu haben. Das sich dann als unvollständig herausstellt. Vielleicht lieg ich aber auch wieder komplett daneben und habs überlesen...
 

Neue Beiträge

Zurück