Theorie für Datenaustauch zwischen Klassen

snowman2

snowman2

Fortgeschrittenes Mitglied
19
Befor ich meine Fragen stelle ersteinmal um was es mir geht.

Ich portiere gerade einen Teil eines C++ Programms nach Java/Android. Dabei geht es um Kommunikation auf dem PC per USB/RS232 und auf Android per Bluetooth.

In C++ habe ich eine struct, in die ich die empfangenen Datenbytes nacheinander und per Pointer schreibe. Wenn ich alle Daten empfangen habe gebe ich einen Pointer vom Typ dieser struct weiter. Ich kann nun direkt auf die einzelnen Felder der struct mit ihren Bezeichner zugreifen.

Das geht in Java ja so nicht. Deswegen ist meine Theorie so: Die struct ersetze ich durch eine Klasse in der sich ein Byte-Datenarray befindet. Nachdem ich alle Daten emfangen habe übergebe ich dieser Klasse das Datenarray mit den emfangenen Daten. Um auf die Daten der Klasse zuzugreifen würde ich der Klasse Seter- und Geter-Methoden hinzufügen, die ihre daten aus dem Byte-Datenarray holen.

Ist dies so sinnvoll? Wenn jemand eine Code-Beispiel oder ein Tutorial dazu hat immer her damit.

Wenn das so ok ist dann meine 2. Frage. Im Datenempfangsthread erzeuge ich für mein Datenpacket ein neues Datenarray, welches ich an meine Activity schicke. Dieses Datenarray wird dann in meiner ober erwähnten Klasse gespeichert. Bei der Übergabe des Datenarrays wird nur die Referenz auf mein Datenarray übergeben. Wenn ich allso folgendes mache
Code:
Klasse.Datenarray = EmpfangsDatenarray
Wird nur die Referenz übernommen. Was passiert mit dem Speicherbereich des alten Inhalt von Klasse.Datenarray? Muss ich den Speicherbereich wieder freigeben? Nicht das es dadurch zu Memoryleaks kommt weil die nicht mehr benötigten allten Daten immernoch im Speicher rumlungern.

Ich hoffe, ihr versteht was ich meine.
 
Ich habe gerade eben noch eine Funktion des Array gefunden und zwar das array.clone(). Das ist wohl aber auch nicht das richtige, da dabei wohl noch ein neues Array im Speicher angelegt wird.

PS: Noch was gefunden:
public static void arraycopy (Object src, int srcPos, Object dst, int dstPos, int length)

Das würde bedeuten:
Im Empfangsthread wird ein Datenarray erzeugt welches das der Activity übergeben wird. In der Activity wird der Messagehandler aufgerufen und das Empfangsdatenarray übergeben. Mit arraycopy werden die Daten in Kasse.datenarray kopiert und am Ende vom Massagehandler wird das Empfangsdatenarray automatisch aus dem Speicher gelöscht. Richtig und sinnvoll?


Ich habe noch diese gefunden:
http://www.sws.bfh.ch/~amrhein/Swing/javainsel7/javainsel_03_009.htm
 
Zuletzt bearbeitet:
Gibt es in Java ein Pendant zu struct und union?
 
snowman2 schrieb:
In C++ habe ich eine struct, in die ich die empfangenen Datenbytes nacheinander und per Pointer schreibe. Wenn ich alle Daten empfangen habe gebe ich einen Pointer vom Typ dieser struct weiter. Ich kann nun direkt auf die einzelnen Felder der struct mit ihren Bezeichner zugreifen.

Das geht in Java ja so nicht.

GIbt es dafür einen konkreten Grund, warum das in Java nicht geht, oder ist der Grund für diese Einschätzung, dass es nichts gibt, was explizit struct heißt?

snowman2 schrieb:
Deswegen ist meine Theorie so: Die struct ersetze ich durch eine Klasse in der sich ein Byte-Datenarray befindet. Nachdem ich alle Daten emfangen habe übergebe ich dieser Klasse das Datenarray mit den emfangenen Daten. Um auf die Daten der Klasse zuzugreifen würde ich der Klasse Seter- und Geter-Methoden hinzufügen, die ihre daten aus dem Byte-Datenarray holen.

Ist dies so sinnvoll? Wenn jemand eine Code-Beispiel oder ein Tutorial dazu hat immer her damit.

Das geht schon.
Du kannst das auch genauso machen wie in C/C++. Es gibt keinen effektiven Unterschied zwischen einer struct und einer Klasse ohne Methoden, in der alle Member public sind.

snowman2 schrieb:
Wenn das so ok ist dann meine 2. Frage. Im Datenempfangsthread erzeuge ich für mein Datenpacket ein neues Datenarray, welches ich an meine Activity schicke. Dieses Datenarray wird dann in meiner ober erwähnten Klasse gespeichert. Bei der Übergabe des Datenarrays wird nur die Referenz auf mein Datenarray übergeben. Wenn ich allso folgendes mache
Code:
Klasse.Datenarray = EmpfangsDatenarray
Wird nur die Referenz übernommen. Was passiert mit dem Speicherbereich des alten Inhalt von Klasse.Datenarray? Muss ich den Speicherbereich wieder freigeben? Nicht das es dadurch zu Memoryleaks kommt weil die nicht mehr benötigten allten Daten immernoch im Speicher rumlungern.

Wenn das die einzige Referenz zu dem alten Array war wird der Speicher vom Garbage-Collector automatisch freigegeben.
Um solche Details der Speicherverwaltung brauchst du dich in der Regel nicht kümmern.

snowman2 schrieb:
Ich habe gerade eben noch eine Funktion des Array gefunden und zwar das array.clone(). Das ist wohl aber auch nicht das richtige, da dabei wohl noch ein neues Array im Speicher angelegt wird.

PS: Noch was gefunden:
public static void arraycopy (Object src, int srcPos, Object dst, int dstPos, int length)

Das würde bedeuten:
Im Empfangsthread wird ein Datenarray erzeugt welches das der Activity übergeben wird. In der Activity wird der Messagehandler aufgerufen und das Empfangsdatenarray übergeben. Mit arraycopy werden die Daten in Kasse.datenarray kopiert und am Ende vom Massagehandler wird das Empfangsdatenarray automatisch aus dem Speicher gelöscht. Richtig und sinnvoll?


Ich habe noch diese gefunden:
http://www.sws.bfh.ch/~amrhein/Swing/javainsel7/javainsel_03_009.htm

Richtig schon, ob es sinnvoll ist kann ich mit Sicherheit jetzt gar nicht beantworten. Ich würde aber vermuten, dass ein Bytearray anlegen und ein anderes freigeben schneller ist als eins zu kopieren. Kann ich aber wie gesagt auch nicht mit Bestimmtheit sagen.
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: snowman2
GIbt es dafür einen konkreten Grund, warum das in Java nicht geht, oder ist der Grund für diese Einschätzung, dass es nichts gibt, was explizit struct heißt?
In C++ greife ich in zwei weise auf die struct zu.
1. In der Empfangsroutine byteweise. Damit befülle ich die struct.
2. Im normalen Programmablauf über die Namen der beinhalteten Variablen.

Damit fällt dann auch folgendes raus:
Das geht schon.
Du kannst das auch genauso machen wie in C/C++. Es gibt keinen effektiven Unterschied zwischen einer struct und einer Klasse ohne Methoden, in der alle Member public sind.
Wenn ich in C eine struct mit zwei char Variablen definiere, weiß ich es wird ein Speicherplatz von 2 Bates belegt. Ist das bei den Klassen in Java auch so?

Richtig schon, ob es sinnvoll ist kann ich mit Sicherheit jetzt gar nicht beantworten. Ich würde aber vermuten, dass ein Bytearray anlegen und ein anderes freigeben schneller ist als eins zu kopieren. Kann ich aber wie gesagt auch nicht mit Bestimmtheit sagen.
Es geht um ca. 16 Bytes große Arrays. Ich will die Speicherverwaltung nicht überlasen :biggrin:
 
Zuletzt bearbeitet:
snowman2 schrieb:
[...]
Das geht in Java ja so nicht. Deswegen ist meine Theorie so: Die struct ersetze ich durch eine Klasse in der sich ein Byte-Datenarray befindet. Nachdem ich alle Daten emfangen habe übergebe ich dieser Klasse das Datenarray mit den emfangenen Daten. Um auf die Daten der Klasse zuzugreifen würde ich der Klasse Seter- und Geter-Methoden hinzufügen, die ihre daten aus dem Byte-Datenarray holen.
Ich weiss nicht ganz genau ob das für deinen Fall sinnvoll ist, klingt aber ok und im folgenden gehe ich davon aus, dass es sinnvoll ist :)

Eine Klasse mit Byte Array und Gettern (Brauchst du die Setter?), die die Daten aus dem Byte Array an der richtigen Stelle holen und in die entsprechenden Objekte gecastet zurück geben klingt auf jeden Fall ok.

snowman2 schrieb:
Wenn das so ok ist dann meine 2. Frage. Im Datenempfangsthread erzeuge ich für mein Datenpacket ein neues Datenarray, welches ich an meine Activity schicke. Dieses Datenarray wird dann in meiner ober erwähnten Klasse gespeichert. Bei der Übergabe des Datenarrays wird nur die Referenz auf mein Datenarray übergeben. Wenn ich allso folgendes mache
Code:
Klasse.Datenarray = EmpfangsDatenarray
Wird nur die Referenz übernommen. Was passiert mit dem Speicherbereich des alten Inhalt von Klasse.Datenarray? Muss ich den Speicherbereich wieder freigeben? Nicht das es dadurch zu Memoryleaks kommt weil die nicht mehr benötigten allten Daten immernoch im Speicher rumlungern.

In Java werden Objekte vom Garbage Collector gelöscht, sobald keine Live-Referenz mehr auf das Objekt besteht. Wenn du also das Array überschreibst, und sonst keiner mehr das Array irgendwo speichert wird der Speicher freigegeben.

Ich würde allerdings so vorgehen, deine Klasse, die das Array hält für jedes Paket neu zu instantiieren und nicht nur das Array austauschen. Damit ist gewährleistet, dass z.B. verschiedene Threads nicht mitten im auslesen der verschiedenen Daten ein neues Datenpaket untergejubelt bekommen.
Achte auf jeden Fall auch auf entsprechende Synchronisation (synchronized Schlüsselwort in Java) um kein unvorhergesehenes Verhalten zu provozieren.


Zu deinen anderen Posts: Das Array kopieren musst du nicht, wenn du für jedes neue Paket ein neues Array erstellst. Gelöscht werden die alten wie schon erwähnt automatisch wenn keine Referenz existiert. Nach deiner bisherigen Beschreibung glaube ich nicht, dass du das Array clonen musst. Zumal man mit .clone() vorsichtig sein sollte. Da muss man schon genau wissen was man tut.

edit:
Kranki schrieb:
Das geht schon.
Du kannst das auch genauso machen wie in C/C++. Es gibt keinen effektiven Unterschied zwischen einer struct und einer Klasse ohne Methoden, in der alle Member public sind.
Mit dem Unterschied, dass man in C/C++ einfach einen Byte Stream als dieses struct zurück geben kann und wenn man dann auf die Member zugreift, diese automatisch an der richtigen Stelle im Bytestream anfangen und korrekt "gecastet" werden, das geht nicht so einfach in Java, da musst du explizit umwandeln, oder andere komplizierte Mechanismen nutzen.

edit2:

snowman2 schrieb:
Wenn ich in C eine struct mit zwei char Variablen definiere, weiß ich es wird ein Speicherplatz von 2 Bates belegt. Ist das bei den Klassen in Java auch so?

Vom Platz her gesehen ja, du kannst aber über die Reihenfolge der beiden Objekte im Speicher keine Rückschluss ziehen. Der Compiler sortiert das um wie er es braucht, das muss nicht mit der Deklarationsreihenfolge übereinstimmen.
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: snowman2
Clone bringt mir wohl garnichts, da der Speicher für den Clone neu reserviert wird. Ist also völlig unnütz.

Ich würde allerdings so vorgehen, deine Klasse, die das Array hält für jedes Paket neu zu instantiieren und nicht nur das Array austauschen. Damit ist gewährleistet, dass z.B. verschiedene Threads nicht mitten im auslesen der verschiedenen Daten ein neues Datenpaket untergejubelt bekommen.
Achte auf jeden Fall auch auf entsprechende Synchronisation (synchronized Schlüsselwort in Java) um kein unvorhergesehenes Verhalten zu provozieren.
Ich glaube das wird so nicht nötig sein.
Ich habe ja 2 Thread die auf das Array zugreifen. Allerdings nacheinander.
- Im Empfangsthread wird das Array neu angelegt und mit Daten befüllt.
- Das Array wird dem Activitythread übergeben - Der Empfangsthread hat jetzt nicht mehr an diesem Array zu suchen.
- In der Acivity wird das Array in der Klasse gespeichert.
- Ich als Benutzer kann nun die Daten Manipulieren und irgendwann zurück zum Bluetooth Gerät schicken.
- Bekomme ich ein neues Array wird im Empfangsthread ein neues Array angelegt.
- In der Activity kann das alte Array dann gelöscht werden (per Garbage Collector) und das neue Array (die Referenz) wird in der Klasse gespeichert.

Alternativ würde ich zwei feste Array nehmen und dann wirklich den Inhalt der Arrays von dem einen in das andere kopieren. Dann hat die Speicherverwaltung weniger zu tun, weil nicht ständig neue Array angelegt und wieder gelöscht werden müssten.

Edit: Aber ich würde Probleme mit der Syncronisation bekommen.
 
Zuletzt bearbeitet:
Noch ne Frage:

Im Empfangsthread definiere ich :
Code:
byte[] databuffer;
Mit dem ersten EMpfangenen Byte reserviere ich den Speicher:
Code:
databuffer = new byte[16];
Mit dem letzten empfangenen Byte sende ich das Array an die Activity:
Code:
MsgHandler.obtainMessage(dataReceived, byteNum, -1, databuffer)
kann ich sofort danach im Empfangsthread databuffer = null setzten? Der Garbage Collector dürfte diesen Speicher ja noch nicht freigeben, weil die Referenze wurde ja an die Activity übergeben, existiert also noch.
Sinn und Zweck dieser Übung währe: Mit dem ersten Byte wird das Array angelegt. Wenn jetzt aber in diesem Datenpacket ein Fehler aufgetreten ist wird das Array nicht an die Activity übergeben ich könnte das Array also nocheinmal benutzen. Ich würde dann das nur neu anlegen, wenn es null ist und es auf null setzten wenn es an die Activity übergeben wurde.

Ich habe jetzt hier schon soviel rumgequatsch jetzt probiere ich es einfach mal aus.
 
Zuletzt bearbeitet:
Die Antwort ist übrigens ja.
 
  • Danke
Reaktionen: deek und snowman2

Ähnliche Themen

M
Antworten
3
Aufrufe
145
moin
M
netfreak
  • netfreak
Antworten
10
Aufrufe
453
netfreak
netfreak
5
Antworten
0
Aufrufe
1.141
586920
5
Zurück
Oben Unten