Warum funktioniert das nicht?

White_Fox

Top Contributor
Moin allerseits

Folgendes wirft eine Exception und ich habe keine Ahnung, warum:
Java:
class TestSerializing{
    class ClassFromArrayList extends ArrayList {
        private Object o;

        void setObject(Object o) {
            this.o = o;
        }

        @Override
        public int hashCode() {
            //...
        }

        @Override
        public boolean equals(Object obj) {
            //...
        }
    }
    
    //...
    
    @Test
    public void testCollectionObjects() {
        //...
        ClassFromArrayList o = new ClassFromArrayList<>();
        
        List list = (List) o;

        for (ValueDescriptor elementDescriptor : listElementValues) {
            list.add(elementDescriptor.value()); //elementDescriptor.value() ist z.B. ein Short = 3145
        }
    }
}

Wer das ganze Drama selber ausprobieren will (sehr viel Code):

Der Test ist unter "...\jComponent Library Sorcerer\jComponent Library Sorcerer\src\test\java\objectprocessor\ObjectProcessorIT.java" zu finden.

Los geht es im letzten Test, ab Zeile 1967, dort fängt die Deserialisierung an. Die Exeption kommt dann in der Klasse "...\jComponent Library Sorcerer\jComponent Library Sorcerer\src\main\java\objectprocessor\GeneralListSliceDescriptor.java" in Zeile 74.

Wenn jemand eine Idee hat warum das nicht läuft, wäre das prima. Ich bin da momentan ziemlich ratlos.
 

KonradN

Super-Moderator
Mitarbeiter
Bitte immer die Details mitliefern: Welche Exception wird genau wo geworfen?

Dann sehe ich kein ...\jComponent Library Sorcerer\jComponent Library Sorcerer\src\test\java\objectprocessor\ObjectProcessorIT.java - Da ist einObjectProcessorTest.java - meinst Du den Test?

Dann wäre die Frage: Welche Java Version? Java 8 hat Probleme mit Dependencies, daher gehe ich mal von Java 11 oder 17 aus. Da hast Du dann Probleme mit Reflection, da DU die notwendigen Module nicht öffnest. Also mit Java 17 bekomme ich:

Unable to make field int java.util.HashMap.threshold accessible: module java.base does not "opens java.util" to unnamed module @2a5c8d3f
java.lang.reflect.InaccessibleObjectException: Unable to make field int java.util.HashMap.threshold accessible: module java.base does not "opens java.util" to unnamed module @2a5c8d3f
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)
at objectprocessor.ObjectDisassembler.createFieldDescriptor(ObjectDisassembler.java:136)
at objectprocessor.ObjectDisassembler.stripDown(ObjectDisassembler.java:93)
at objectprocessor.ObjectDisassembler.stripDown(ObjectDisassembler.java:97)
at objectprocessor.ObjectDisassembler.disassemble(ObjectDisassembler.java:60)

==> Wenn Du in vorhandenen Klassen so auf Internas zugreifen willst, dann musst Du das Modul für dich öffnen. Was genau wie geöffnet werden muss, gibt die Fehlermeldung exakt an:

module java.base does not "opens java.util" to unnamed module

Somit musst du java.base/jav.util öffnen für ALL-UNNAME was über den Parameter --add-opens java.base/java.util=ALL-UNNAMED geht.

Du musst also sicher stellen, dass bei Aufrufen genau diese mit an die JVM übergeben wird.
 

White_Fox

Top Contributor
Dann sehe ich kein ...\jComponent Library Sorcerer\jComponent Library Sorcerer\src\test\java\objectprocessor\ObjectProcessorIT.java - Da ist einObjectProcessorTest.java - meinst Du den Test?
Nein, IT ist schon richtig. Möglicherweise falscher Zweig, schau mal ob du auf dem Zweig "ObjectProcessor" unterwegs bist.

Edit:
Die Exception ist eine Nullpointer-Exception. Obwohl da kein Argument null ist.

Und noch ein Edit:
Das wird alles unnamed geöffnet...das Modulsystem sollte ich in Gradle bereits abgeschaltet haben. Ansonsten funktioniert der Reflectionzugriff eigentlich. Aber diese Klasse, um die es hier geht, soll den Zugriff per Reflection eigentlich vermeiden. Da möchte ich Listen (und Sets und Maps) über die normale Standard-API behandeln.
 

KonradN

Super-Moderator
Mitarbeiter
Du machst es einem nicht gerade leicht, Dir zu helfen....

Erlaube mir, erst einmal etwas Frust los zu werden (Einfach überspringen, aber ggf. willst Du da auch etwas sauberer werden ...)

a) Was für eine Java Version verwendest Du? Muss ja 19 oder 20 sein (ersteres wegen Thread.threadId() was es ab 19 gibt und max 20 weil es Gradle 8.3 nutzt? Ich habe es jetzt mit 19 versucht ... Hint: Geh auf eine LTS Version, also ich würde empfehlen, Gradle zu aktualisieren und dann auf 21 zu gehen als eine LTS Version.

b) Dann kriege ich den Branch nicht übersetzt wegen der JavaFX 16 Abhängigkeit - verstehe ich nicht, aber warum JavaFX 16? Habe ich dann jetzt auch einmal auf 19 gesetzt ... Dann noch JUnit 4 und 5 gleichzeitig? Hmm ... ok ...Hint: Halte abhängigkeiten halbwegs aktuell...

Ok, dann das eigentliche Problem:

  • Du hast eine innere Klasse welche von ArrayList erbt. Das ist erst einmal ok.
  • Du erzeugst davon Elemente per obenesis. Obenesis erzeugt Instancen aber mit JVM internas und umgeht den Konstruktor Aufruf. Siehe dazu evtl. auch https://www.baeldung.com/java-objenesis-introduction.
  • Da der Konstruktor von ArrayList nicht aufgerufen wird, ist die interne Membervariable elementData null und Du bekommst bei einem add Aufruf eine NPE.

Da ich aber nicht wirklich im Detail verstehe, was Du mit dem Projekt erreichen willst und was z.B. gegen die üblichen "Seraialisierungen" spricht, kann ich Dir nicht wirklich Lösungswege raten. Man kann natürlich speziell für die ArrayList per reflection auf elementData zugreifen um dies dann zu setzen. Oder man greift halt doch auf den Konstruktor zurück... Ist halt eine Frage der genauen Anforderungen, dass man da ein Design baut, dass eben den Umstand in Betracht zieht, dass Obenesis keine Konstruktoren aufruft und dadurch halt Variablen nicht initialisiert sind...
 

White_Fox

Top Contributor
So...jetzt die ausführliche Antwort.

a) Ich benutze Java 21

b) JavaFX 16 war, als ich das in Projekt nach Gradle migriert habe, wahrscheinlich die aktuelle Version. Ja...ich könnte mal nachschauen ob es da was neueres gibt, da hast du Recht. JUnit4 und 5 aus Abwärtskompatibilitätsgründen. Fast alle Unittests sind zu JUnit4-Zeiten entstanden.

Zum eigentlichen Problem:
Ich will Objekte serialisieren (und – das fällt nebenbei mit ab – klonen). Vorrangig von mir selbst geschriebene Klassen. Ich habe damals, schon etwas länger her, aus verschiedenen Gründen (und nach einigen Diskussionen hier und Tests bereits existierender Lösungen) etwas eigenes aufgesetzt. Einige Gründe waren, daß ich einerseits Zirkelbeziehungen auflösen wollte, und mich andererseits nicht darauf verlassen wollte das eingebundene Bibliotheken auch stets das Serialisable-Interface implementieren.
Das funktioniert indem ich alle möglichen Informationen über über Reflexion – wie auch sonst – zusammentrage und in verschiedenen Deskriptor-Objekten ablegen.

Einige Klassen – dazu gehören Listen, Sets und Maps aus der JSB – möchte ich allerdings nicht über Reflexion untersuchen und darin herumfummeln, sondern möchte diese Klassen über die öffentliche Standard-API lesen und schreiben. Und genau das schlägt hier fehl.

Mal eine kurze Beschreibung, wie das funktioniert: Jedes Objekt wird klassenweise behandelt: das nenne ich in dem Projekt einen "ObjectSlice", um Verwechslungen mit Klassen und (vollständigen) Objekten zu vermeiden. Der ganze Prozess läuft in vier Teilschritten ab:
  1. Disassemblieren Dabei wird ein Objekt bis rauf zur Klasse "Objekt" untersucht, und für jede Klasse – bis auf Objekt, das untersuche ich nicht – wird für jede Klasse, der das Objekt angehört ein ObjectSliceDescriptor-Objekt angelegt (das wiederum Deskriptoren für alle Feldvariablen enthält). Auf diesem Weg gefundene Objekte, die weder String, Array, Enumeration oder ein primitiver Datentyp sind, werden ebenfalls so durchprozessiert.
  2. Serialisieren Macht aus allen Deskriptoren Bytesalat (der dann verschlüsselt, über das Netzwerk geschoben oder in eine Datei geschrieben werden kann).
  3. Deserialisieren Macht aus Bytesalat wieder Deskriptoren.
  4. Assemblieren Das ist die Stelle, an der mein Test Probleme bereitet. Zunächst wird für alle Objekte, die beim Disassemblieren gefunden wurden, ein Äquivalent instantiert. Das macht Objenesis für mich. Danach, wenn alle Objekte erstellt sind, werden die Feldvariablen jedes Objekts wiederhergestellt. Entwder über Reflexion (was hier nicht der Fall ist) oder über die öffentliche API.
 

White_Fox

Top Contributor
So, ich habe den Fehler gefunden:

ArrayList enthält eine Membervariable transient Object[] elementData;, die nach dem Instantieren mit Objenesis null ist. Die Methode add(Object o) schreibt natürlich darauf herum, womit die Nullpointerexception (...Cannot read...because elementData is null) Sinn ergibt.

Jetzt ist dennoch die Frage: Wie lösen...

Edit: Ich werde mich morgen mal intensiver mit der Funktionsweise von Objenesis beschäftigen.
 
Zuletzt bearbeitet:

KonradN

Super-Moderator
Mitarbeiter
Das Kernproblem ist, dass Objenesis keinen Konstruktor nutzt. Wieso nutzt Du nicht einfach einen Konstruktor: Du kannst die notwendige Klasse laden und die vorhandenen Konstruktoren anschauen um dann einen passablen Konstruktor zu finden. Das löst das Problem sofort. (Wobei die Frage ist, ob das Schauen nach einem Standard Konstruktor nicht ausreichend ist.... Denn wenn es den nicht gibt ist alles direkt ein Unding. Maximal schauen, ob Du an Parametern evtl. hast, was Du auch an Werten hast von Serialisieren?)

Aber das ist halt das Kernproblem das Du immer hast. Gib eine Lösung an, mit der eine eigene Lösung für Serialisierung / Deserialisierung gegeben werden kann. Das ist ja auch Standard...

Also um es ganz deutlich zu sagen:
Zunächst wird für alle Objekte, die beim Disassemblieren gefunden wurden, ein Äquivalent instantiert. Das macht Objenesis für mich.
Das was Du diesbezüglich gebaut hast, ist absoluter Murks. Mit irgendwelchen JVM Internas Objekte zu bauen ohne den Konstruktor zu bemühen kann nur zu Problemen führen!
 

White_Fox

Top Contributor
Du kannst die notwendige Klasse laden und die vorhandenen Konstruktoren anschauen um dann einen passablen Konstruktor zu finden.
Tja, das habe ich anfangs genau so gemacht. Und bin dann in genau diese Fragestellung hineingelaufen: Was, wenn es keinen parameterlosen Konstruktor gibt? Einen Konstruktor kannst du ja auch nicht mit beliebigen Werten füllen, ich sehe dem Konstruktor ja schließlich nicht an ob die Parameter innerhalb irgendwelcher Grenzen liegen müssen.
Deshalb hatte ich Objenesis eingesetzt...aber da hatte ich wohl falsche Erwartungen an die Bibliothek.

Aber gut, das kriege ich auch noch irgendwie gelöst, notfalls muß meine alte Lösung mit dem Konstruktoraufruf wieder her. Eine Option für Sonderlocken bei der Objektinstantierung wollte ich sowieso noch einbauen.
 

KonradN

Super-Moderator
Mitarbeiter
Der übliche Ansatz ist, dass man abdeckt, was eben direkt abdeckbar ist. Da gibt es dann gewisse Begrenzungen z.B. bezüglich eines Konstruktors, der vorhanden sein muss. In dem Moment, wo sowas nicht vorhanden ist, dann bieten die meisten Lösungen Adapter an. Du hast also einen Typ, der einen speziellen Konstruktor hat? Dann musst Du für diesen Typ eine Serialisierung und Deserialisierung vorgeben. Bei Gson sind das dann z.B. JsonSerializer<T> und JsonDeserializer<T>, die man implementieren müsste.

Der Ansatz ist also sehr problematisch. Und auch generell wäre ich immer extrem vorsichtig, wenn man plötzlich mit JVM Dingen herum tricksen möchte. Diese Library, die Objekte erzeugt, ohne dass der Konstruktor aufgerufen wird: sowas lässt es mit kalt den Rücken herunter laufen. Das schreit ja nur geradezu nach Problemen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G WSDL-Aufruf funktioniert nicht mehr nach Umstieg auf Maven Allgemeine Java-Themen 4
Zrebna Berechnung der Zeit funktioniert nicht wie erwartet: Date, GregorianCalendar Allgemeine Java-Themen 16
M Apache Proxy Weiterleitung auf Tomcat funktioniert nicht wie gewünscht Allgemeine Java-Themen 1
W While Schleife funktioniert nicht ganz Allgemeine Java-Themen 4
H do-while Schleife funktioniert nicht wie ich es möchte Allgemeine Java-Themen 7
ERlK JDA Code funktioniert nicht? Allgemeine Java-Themen 4
stormyark TikTakToe funktioniert nicht Allgemeine Java-Themen 10
T Remove bei ArrayList funktioniert nicht Allgemeine Java-Themen 2
M Map<String,String>funktioniert nicht richtig Allgemeine Java-Themen 4
P String.replace() funktioniert nicht? Allgemeine Java-Themen 3
boschl2000 Springerproblem-Implementierung funktioniert nicht richtig Allgemeine Java-Themen 1
F Getter Methode aufrufen funktioniert nicht Allgemeine Java-Themen 1
N Regulärer Ausdruck funktioniert nicht Allgemeine Java-Themen 6
Tobero Meine Funktion für das beinhalten eines Punktes in einem Kreis funktioniert nicht Allgemeine Java-Themen 5
1Raini Java if-Abfrage funktioniert nicht! Allgemeine Java-Themen 3
Killunox MaxHeap Zuweisung unter Linux funktioniert nicht Allgemeine Java-Themen 1
Dann07 MP3 Datei abspielen funktioniert nicht Allgemeine Java-Themen 6
O Aus JAR-Datei erstellte EXE-Datei funktioniert nicht Allgemeine Java-Themen 10
A Mp3 Player funktioniert nicht Allgemeine Java-Themen 0
X JNA funktioniert nicht mehr Allgemeine Java-Themen 4
Drachenbauer Division mit Int funktioniert nicht Allgemeine Java-Themen 3
O docx-Datei erzeugung mit DocXStamper funktioniert nicht Allgemeine Java-Themen 2
F Schleife funktioniert nicht richtig Allgemeine Java-Themen 13
T Split() Methode funktioniert nicht?! Allgemeine Java-Themen 11
L Tesseract-OCR 4.0 unter Linux funktioniert nicht Allgemeine Java-Themen 3
J Neuronales Netz funktioniert mal und mal nicht. Allgemeine Java-Themen 3
T Umlaute in Eclipse einlesen funktioniert nicht Allgemeine Java-Themen 16
A Methodenaufruf funktioniert nicht richtig Allgemeine Java-Themen 5
C WindowBuilder Design funktioniert nicht Allgemeine Java-Themen 0
J FTPSClient funktioniert nicht Allgemeine Java-Themen 4
H IDEA IntelliJ Java Mail funktioniert nach Export nicht mehr! Allgemeine Java-Themen 1
M Operatoren Warum funktioniert diese überprüfung nicht? Allgemeine Java-Themen 7
R jar-Datei funktioniert nicht Allgemeine Java-Themen 2
E Open Declaration Funktioniert nicht Allgemeine Java-Themen 0
R Verschlüsselung funktioniert nicht Allgemeine Java-Themen 5
RalleYTN requires transitive funktioniert nicht? Allgemeine Java-Themen 7
P Best Practice Wieso funktioniert der Modulo - Operator nicht? Allgemeine Java-Themen 2
HarleyDavidson Eigener PropertyChangeListener funktioniert einfach nicht Allgemeine Java-Themen 3
J Exclude funktioniert nicht Allgemeine Java-Themen 2
K .jar funktioniert nicht vollständig Allgemeine Java-Themen 1
P Java https proxy (-Dhttps.proxyHost) Start-Parameter funktioniert nicht? Allgemeine Java-Themen 2
L Auswertung eines Testes funktioniert nicht Allgemeine Java-Themen 37
O Fahrenheit/Celsius Converter funktioniert nicht Allgemeine Java-Themen 2
M Serialisierung funktioniert nicht Allgemeine Java-Themen 9
D Collections.sort funktioniert nicht in exportierten .class Dateien Allgemeine Java-Themen 10
J Arrays auf gleichheit untersuchen funktioniert nicht Allgemeine Java-Themen 11
P GUI: ArrayList anzeigen funktioniert nicht Allgemeine Java-Themen 5
H Timer funktioniert nicht? Allgemeine Java-Themen 3
R javax.comm --> Programm funktioniert nach Export nicht mehr Allgemeine Java-Themen 0
O Mein JButton Array funktioniert nicht Allgemeine Java-Themen 3
R Erste Schritte Object reference funktioniert nicht. Wie mach ichs richtig? Allgemeine Java-Themen 3
J If Abfrage funktioniert nicht Allgemeine Java-Themen 4
R Objekt funktioniert nicht auf iOS Allgemeine Java-Themen 15
U PersistenceManager.createEntityManager funktioniert nicht Allgemeine Java-Themen 3
D Java Datei nach Eclipse Export funktioniert nicht Allgemeine Java-Themen 0
M Eigene forEach()-Methode funktioniert nicht. Allgemeine Java-Themen 2
H File.listFiles() funktioniert nicht... Allgemeine Java-Themen 10
JG12111989 Auswertung von Fragebogen funktioniert nicht! Allgemeine Java-Themen 7
M Primzahlberechnung funktioniert nicht. Allgemeine Java-Themen 4
A JFreeChart funktioniert nicht :( Allgemeine Java-Themen 6
C file.delete() funktioniert bei zweiten aufruf nicht mehr Allgemeine Java-Themen 3
F Datei einlesen funktioniert nicht Allgemeine Java-Themen 3
A Debugger im Java-Editor funktioniert nicht Allgemeine Java-Themen 5
B DB-Zugriff einer Webanwendung funktioniert nicht mit Java 7 Allgemeine Java-Themen 2
B Web-Anwendung funktioniert mit Java 1.8, aber nicht mit Java 1.7 (auf Client) Allgemeine Java-Themen 5
J Swing Cursor.WAIT funktioniert nicht nach JFileChooser Allgemeine Java-Themen 1
F JTextField funktioniert nicht Allgemeine Java-Themen 6
Athena Programm funktioniert nur beim Debugging korrekt, sonst nicht. Allgemeine Java-Themen 1
S CSV Eintrag der nächsten Zeile auslesen funktioniert nicht Allgemeine Java-Themen 8
S Command funktioniert in Kommandzeile aber nicht mit ProcessBuilder bzw. Runtime.exec auf MAC Allgemeine Java-Themen 3
G Verschlüsselungsalgorythmus funktioniert nicht Allgemeine Java-Themen 2
buggy84 Ausführen einer Batch mit Parameterübergabe funktioniert nicht richtig Allgemeine Java-Themen 18
G Befehl funktioniert in Eclipse allerdings nicht in einer Jar-Datei Allgemeine Java-Themen 3
N Werte aus Arrays auslesen funktioniert nicht Allgemeine Java-Themen 5
W getResources funktioniert nur in Eclipse, nicht in JAR Allgemeine Java-Themen 2
S Methode funktioniert nicht als ActionListener Allgemeine Java-Themen 4
M exec() funktioniert nicht Allgemeine Java-Themen 1
X Datentypen Dropzone.options funktioniert nicht Allgemeine Java-Themen 1
L Erste Schritte Eclipse und Lokal funktioniert - in HTML nicht! Allgemeine Java-Themen 2
K MD5 funktioniert nicht korrekt !? Allgemeine Java-Themen 9
M JAR Datei erstellen funktioniert nicht Allgemeine Java-Themen 5
Q JLabel Textausgabe funktioniert nicht Allgemeine Java-Themen 4
E SimpleDateFormat-Konvertierung funktioniert nicht Allgemeine Java-Themen 3
T Dateidownload Funktioniert nicht Allgemeine Java-Themen 4
K String.replace funktioniert nicht Allgemeine Java-Themen 3
G treeMap.putall funktioniert nicht?! Allgemeine Java-Themen 2
DaniSahne96 Threads Code funktioniert nicht wie er sollte Allgemeine Java-Themen 9
S Warum funktioniert die runable -.jar nicht? Allgemeine Java-Themen 7
P Eclipse Unter Windows erstelle .jar unter Linux (Ubuntu) funktioniert nicht Allgemeine Java-Themen 5
H Mit Ant erstelltes jar funktioniert nicht wie direkt in Eclipse Allgemeine Java-Themen 8
aze Jar ausführen über Runtime.execute funktioniert nicht Allgemeine Java-Themen 4
M Normalized Iteration count funktioniert nicht. Wo ist mien Denkfehler? Allgemeine Java-Themen 6
M Input/Output Datei erzeugen funktioniert nicht (immer) vom .jar aus Allgemeine Java-Themen 5
P Klassen Junit test funktioniert nicht... Allgemeine Java-Themen 11
H Kompilieren funktioniert nicht Allgemeine Java-Themen 4
L repaint() methode funktioniert nicht richtig! Allgemeine Java-Themen 3
M FTP [vfs] SFTP via VFS 2.0, Dateiübertragung funktioniert nicht Allgemeine Java-Themen 2
A String.split() funktioniert nicht richtig Allgemeine Java-Themen 4
H PrinterJob.getPageFormat() funktioniert nicht Allgemeine Java-Themen 4
GUI-Programmer Jar File funktioniert nicht auf PC2, auf PC1 schon Allgemeine Java-Themen 13

Ähnliche Java Themen

Neue Themen


Oben