Der Heap Space, ich weiß nicht mehr weiter!

  • Themenstarter Themenstarter Bebbo Erbse
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
B

Bebbo Erbse

Gast
Hallo liebes Forum!
Ich hatte sehr mühsam an einem Programm gearbeitet, dass auch Bilderdaten(von 3.75 MB) verabeiten muss. Anfangs hatte ich ein Java Heap Space Problem, da ich so dumm war und zum Verarbeiten. der Bilddaten String-Objekte benutzt haben. Dann musste ich von neuem beginnen und habe Performance-orientiert gearbeitet(also int-arrays) verwendet. Nun lässt sich aber wieder dieses Problem nicht vermeiden. Ich habe zwar meinen Heap Space auf bis zu 1024 MB reservieren lassen, aber das hilft nichts. Gab es da nicht einen Befehl, wo ich die ganzen nicht mehr verwendeten Objekte raushauen kann? Ich entsinne mich leider nicht, welcher das war.
Wisst ihr da was? Notfalls muss ich jemandem mein Programm schicken, damit er es sich mal anschaut. Ich probier nun erstmal aus den int-arrays byte-arrays zu machen, vielleicht bringt das noch was.

Vielen Dank für die Hilfe!
 
Runtime#gc() :bahnhof:

aber ich tippe mal auf nen programmierfehler. du hältst nicht zufällig alle bilddateien immer im speicher? 8) profile doch mal!
 
Ich habs nun erstmal hinbekommen, dass es läuft. Die Performance passt zwar, aber das einzige Problem ist, dass es erst ab 512 MB RAM reicht...
Also mein Programm lädt die Bilddaten(z.b. 3,5Mb) in ein Array. An das Array kommt noch ein Feld dran, wo den Bilddaten Bitpositionen in einer Geheimdatei(die später in dem Bild versteckt wird) zugeordnet werden.
Das ganze kann man sich wie folgende Tabelle vorstellen:

int array[Bilddaten in Byte][zugeordnete Positionen][zugeordnete Positionen2]

Es können bis zu 8 zugeordnete Positionen hinzugefügt werden! Also reserviert er theoretisch, wenn die Bilddatei(BMP-Datei) 1024*768 Pixel(*3 Bildpunkte) erstmal 2359296 Felder(ohne die Null-Bytes der BMP-Datei). Ein Feld hält ja einen int wert, also wäre es 4 Byte groß. Das wären dann für die Bilddaten schon 4*2359296 = 9437184 Byte = 9 MB. Nun kommt ja noch mal so ein Feld mit den zugeordneten Positionen dazu, also wären das 9*(Anzahl von den Positionsfeldern, das sind maximal 8). Aber das sind dann doch auch nicht so viel MB, die benötigt werden...
Ich suche noch einen Befehl, mit dem ich eventuell nicht mehr verwendete Objekte(solche Felder) aus dem RAM rausholen kann.
 
Moin Moin


Bebbo Erbse hat gesagt.:
Ich suche noch einen Befehl, mit dem ich eventuell nicht mehr verwendete Objekte(solche Felder) aus dem RAM rausholen kann.

Den Garbage Collector kannst du mit
Code:
System.gc();
anwerfen. Nur ist dieses kein direkter Befehl sondern nur ein Hinweis an die VM. Die VM wird aktiv wenn sie Zeit und Lust hat.

Zu Beachten:
Der GC wirft nur die Objecte weg die keine Verbindung mehr zu aktiven Objecten haben.
Hab im letzen Jahr die selben Probleme gehabt und kann dir sagen =>
Code:
System.gc();
bringt nichts! Die VM wirft den GC an wenn sie es möchte/kann. Programmierung optimieren (Unter Forum Performance).

Und wirf mal einen Profiler an um zu sehen was wann erzeugt und wann es wieder gelöscht wird. Du hast sicherlich noch irgendwo eine Verbindung zu grade nicht benötigte Arrays. Mußt du immer alle Array im Ram haben?

cu Ontos
 
Hm... Danke für den Tipp! Das mit dem " System.gc(); " hatte ich auch schonmal probiert(nur hab ich diese Anweisung vergessen) und damals hats auch nichts gebracht.
Also eigendlich brauche ich nicht alle, ich weiß aber nicht, welche Objekte noch als aktiv gelten. Ich kann ja mal einen Ausschnitt meines Programms posten:

Code:
// Klasse distributor.java

	public static int[][] lead(int[] buffer) {
		int[][] stegamap;
		datastop = (7*8) + (datalength%CBMP.bitperbyte) + ((datalength-(datalength%CBMP.bitperbyte))/CBMP.bitperbyte);    // Kann ignoriert werden
		stegamap = distribute(buffer);     // Achtung: Diese distribute-Methode ist eine andere, als die, die im folgenden gemeint ist. 
                                                                 //Der Schritt tut also kaum was zur Sache, er setzt lediglich die erste Datenbitpositionenreihe an stegamap
		for(int i = 1; i < CBMP.bitperbyte; i++) {
			fields = i+1;
			datastart = datastop;  // kann auch ignoriert werden
			datastop += (datalength-(datalength%CBMP.bitperbyte))/CBMP.bitperbyte;  // kann auch ignoriert werden
			stegamap = distribute(stegamap);
		}
		return stegamap;
	}

// Also, zur Erklärung:
//Diese Methode fordert die Bilddaten als int-array(buffer[]). Zurückgegeben wird das zweidimensionale Array stegamap, wobei man sich das wie oben vorstellen kann(sodass 
//den Bilddaten noch bestimmte Positionen von Datenbits zugeordnet sind). Die Methode distribute erweitert dieses Feld um eine Dimension, um noch eine Reihe von 
//zugeordneten Datenbitpositionen hinzuzufügen und diese Positionen dann zuzuweisen:

	public static int[][] distribute(int[][] stegamap) {
		
		int[][] expanded_stegamap = new int[bufferlength][fields+1];    // Hier wird eben eine Reihe hinzugefügt
		
		
		for(int fieldnumber=0; fieldnumber<fields; fieldnumber++) {    // Hier wird das übergebene Array mit der expanded_stegamap erstmal gleichgesetzt(werte werden übertragen)
			for(int pointer=0; pointer < bufferlength; pointer++) {
				expanded_stegamap[pointer][fieldnumber] = stegamap[pointer][fieldnumber];
			}
		}
		for(int i = 0; i < bufferlength; i++) {   // Hier wird die extraspalte mit -1 gefüllt
			expanded_stegamap[i][fields] = -1;
		}

// Die methode geht dann weiter
		return expanded_stegamap;
	}

Nun nochmal ein Beispiel.
Ich habe erst das Array Buffer[] mit den Bilddaten.
Danach ein erstes Array Stegamap, was so aussieht: stegamap[Bilddaten][Datenbitpositionen]. Nach unten hin verlaufen eben wie in einer Tabelle die Daten. Dann soll eben noch eine Reihe hinzugefügt werden, sodass das dann so aussieht: stegamap[Bilddaten][Datenbitpositionen][Datenbitpositionen2]
Bis zu 8 werden maximal hinzugefügt. Das hinzufügen und zuweisen der Datenbitpositionen geschieht über die methode distribute. Wie das geschieht ist hier eigendlich egal. Ich denke, dass das wesentliche Problem im geposteten Code ist.

Ich bin leider gezwungen int-Arrays zu benutzen, weil die zugeordneten Datenbitpositionen höhere Werte erreichen können...
 
Wenn Du das Programm startest, setzt Du dann mir der "-Xmx"-Option die maximalen Heap-Größe?
Hintergrund der Frage ist, dass nach meiner Erfahrung der Garbage-Collector erst dann anspringt, wenn man sich
wirklich hart an der Grenze des verfügbaren Speichers bewegt. Wenn man sich also mit -Xmx eine grossen
Speicherbereich "zur Sicherheit" reservieren will, dann muss man damit rechnen, dass dieser Speicher auch belegt wird.
 
falls sich jemand wundert warum das ganze unlesbar ist
-> zu langer Kommentar im Codeteil, bitte Zeilenumbrüche einfügen..
 
Tut mir Leid! Ich kann den Kommentar nun icht mehr kürzen.
Ja, ich setze die maximale Heap-Größe. Aber, dass 256 MB nicht mehr ausreichen, kann ich mir einfach nicht vorstellen. Jemand mit 256 MB RAM wäre also nicht im Stande das Programm zum Laufen zu bringen. Gibt es denn an den Codestellen noch irgendwas Performancemäßig zu verbessern? Ich bin mit ziemlich sicher, dass es an der Stelle liegt, da dort mit 256 MB Heap Size bereits eine Fehlermeldung kommt...
 
Bei 256 MB bekommst Du einen OutOfMemoryError? Dann wird wirklich soviel Speicher verbraucht.
Ich dachte, Du wunderst Dich nur über den Speicherverbrauch. In solchen Fällen kann es wirklich so
sein, dass ein an sich korrektes Programm sich fast den gesamten mit -Xmx definierten Speicher greift,
bevor der GC eingreift - bevor es zu einer Exception kommt, wird dann aber auf jeden Fall collected.
 
also wenn ich Stegeanographie machen müsste

dann würde ich das bild laden

eventuell in Rot-Grün-Blau zerlegen

das Geheimnis "in einem Durchlauf" in die niederwertigen bits hineinmischen

fertig

was soll das getue mit
Code:
tegamap[Bilddaten][Datenbitpositionen].
wozu muss so ein Array überhaupt erzeugt werden?
 
Nunja, da steckt natürlich schon eine Funktion dahinter:
Die Bits werden nicht einfach hintereinander reinversteckt. Erst werden die Bits der Datendatei durcheinandergewürfelt und irgendwo in den Bilddaten verteilt. Die Positionen sind dabei abhängig vom eingegebenem Passwort. Dabei muss ich ja zum einen festhalten, um welches Datenbit es sich handelt(Also die Bitnummer von der ganzen Datendatei) und wo sie im Bild versteckt wird. Und dazu brauch ich halt das Feld...
 
ist doch quark, wenn du ein passwort hast dann verschlüssle eben mit AES oder DESEDE, dann wird mehr oder weniger ein Zufallsstrom hineingemischt


Tipp:

byte[A]

benötigt Speicher in der Grössenordnung A*B


Code:
      for(int i = 1; i < CBMP.bitperbyte; i++) {
         fields = i+1;
         datastart = datastop;  // kann auch ignoriert werden
         datastop += (datalength-(datalength%CBMP.bitperbyte))/CBMP.bitperbyte;  // kann auch ignoriert werden
         stegamap = distribute(stegamap); // WAHNSINN
         // IN JEDEM SCHLEIFENDURCHLAUF
         // RIESIGE ARRAYS ERZEUGEN
      }
 
Nunja, es soll für Außenstehende aber schwieriger sein überhaupt zu erkennen, dass dort eine Versteckte Nachricht vorliegt... Und das mit dem byte[]-Array geht leider nicht. Daran hatte ich auch schon gedacht, aber das ganze sähe ja dann so aus:

stegamap[Bilddaten][Bitpositionen]

Die Bilddaten können als byte-Wert genommen werden, aber die Bitpositionen erreichen durchaus sehr hohe Werte, wofür ich wiederum einen Integer-Type benötige... Ich glaube für dieses Problem gibt es keine richtige Lösung...
 
Nunja, es soll für Außenstehende aber schwieriger sein überhaupt zu erkennen, dass dort eine Versteckte Nachricht vorliegt.
deshalb verschlüssle mit AES oder einer anderen symmetrischen Chiffre, es entsteht ein byte-Array das "praktisch" wie ein Zufallsstrom von Bytes aussieht

=> wenn du dieses direkt z.B. in das niegrigste Bit von "Rot" einmischt, dann wäre es schon sehr schwer, dieses "Rauschen" als Nachricht zu erkennen

kannst du mal erklären wie das mit den "Bitpositionen" genau funktionieren soll?
 
Hallo, das mit dem AES klingt sehr interessant, das könnte ich zur zusätzlichen Verschlüsselung noch nehmen!
Gibt es dafür schon vordefinierte Java-Klassen? Und welche sind das?

Also das Vermischen der Datenbits im Bild soll ja nicht mit der Verschlüsslung gleichgesetzt werden.
Es wird lediglich die Nachricht nochmal im Bild verteilt, statt in jedem Rot-Anteil hintereinander etwas zu verstecken.

Hier mal Ein Beispiel:

Ich nehme den Buchstaben "A" als Geheimtext.
Jetzt zerlege ich den Buchstaben in seine Bits(nach dem ASCII Code).
Also... A = 65 = 01000001(bit)

Ich denke mir jetzt folgende Tabelle:

Bitpositionen: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
------------------------------------------------
Bits_______: 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |


Jetzt habe z.b. folgende Bilddaten in das Array geladen(Jeden Rot- Grün- oder Blau-Anteil hintereinander):

________(_R__G__B_|_R___G__B_|_R__G___B_|_R_|_G_|_B_)
Bilddaten: FF | FF | FF | 00 | 00 | 00 | FF | FF | FF | 00 | 00 | 00 |

Das R/G/B obendrüber kommt natürlich nicht in die Tabelle.
Es soll jetzt nur als Veranschaulichung dienen. Aslo, mein Bild hat nun 4 Pixel(abwechselnd weiß/schwarz).

Jetzt kommt die distributor-methode ins Spiel. Sie nimmt sich jetzt die Bilddaten und fügt noch eine Zeile
mit den zugeordneten Bitpositionen hinzu. In diesem Beispiel verstecke ich nur ein Bit in einem Byte, sodass
ich nur eine Zeile hinzufügen muss:

Bilddaten___: FF | FF | FF | 00 | 00 | 00 | FF | FF | FF | 00 | 00 | 00 |
----------------------------------------------------------------------------------|
Bitpositionen: 07 |02 |--- |04 | --- | --- | --- | 06 |03 | 01 | 05 | 00 |


Jetzt wird das diesem Farbanteil also sozusagen ein Bit zugewiesen, was in dem Array durch die Position des Bits
im Gesamtgeheimtext dargestellt wird.


Also werden in die Bilddaten wie folgt verändert:

Farbanteil --> Verstecktes Bit(Position des Bits im Geheimtext) --> Resultierender Farbanteil mit verstecktem Bit

FF --> 1(07) --> FF
FF --> 0(02) --> FE
FF --> keins --> FF
--
00 --> 0(04) --> 00
00 --> keins --> 00
00 --> keins --> 00
--
FF --> keins --> FF
FF --> 0(06) --> FE
FF --> 0(03) --> FE
--
00 --> 1(01) --> 01
00 --> 0(05) --> 00
00 --> 0(00) --> 00

Ich hab die Bilddaten jetzt mal zur Übersicht von oben nach unten gelistet.
Achso, der Geheimtext "A" kann natürlich schon bevor er in seine bits zerlegt wird, verschlüsselt werden.
Die Positionszuweisung bei der distributor-methode geschieht unterschiedlich, je nach eingegebenem Passwort. Demnach ist beim Extrahieren der Nachricht aus einem Bild auch das richtige Passwort notwendig, um die Positionen des der Farbanteile und die Reihenfolge der Bits herauszubekommen.

Ich gebe zu das ganze ist etwas verwirrend und ich hoffe, dass hier ohne Fehler dargestellt zu haben.
Würde man 2 Nachrichtenbits in einem Byte verstecken, dann müsste man oben nur eine weitere Zeile
mit Bitpositionen hinzufügen...[/u]
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben