Ich habe Ich habe die Quelle von ArrayList gelesen gelesen. Seit ich die JDK-Quelle gelesen habe, habe ich über die ungelösten Punkte nachgedacht (4 Stellen). Bitte ersetzen Sie IntMax im Text durch Integer.MAX_VALUE. Es war mühsam zu schreiben. Zuerst habe ich intMax geschrieben, aber es hat sich in IntMax geändert. was ist das.
Dies ist die Antwort in Teil 4.
"LL.760-763 Der Grund, warum elementData absichtlich auf vorübergehend gesetzt und nicht von defaultWriteObject () ausgeschrieben wird, besteht darin, zu vermeiden, dass mehr als die Größe von elementData vergeblich ausgeschrieben wird. !! 』
Es ist eine Verschwendung, null, null, null nach der Größe auszugeben.
Aber ich weiß nicht, warum ich s.writeInt (Größe) mache; Wo ist die Kompatibilität von clone ()! ??
Es scheint zu sein, die serialisierten Felder von Javadoc auszugeben. Ich wusste es heute zum ersten Mal. Serialisiertes Format In den zugehörigen Elementen der ArrayList-Klasse befindet sich ein Link, der als serialisiertes Format bezeichnet wird.
(Ergänzung) Ich habe "hier" als "hier" missverstanden. Warum war es in der Größe, aber nicht in elementData? Haben Sie es weggelassen, weil es vorübergehend ist? Aber sollte ich es hinzufügen, weil es mit writeObject und readObject serialisiert ist? Ich weiß es nicht, weil ich @serial noch nie hinzugefügt habe. ungelöst.
"Nahe dem Maximalwert von int → Wenn es um das 1,5-fache überläuft und zu einem relativ kleinen negativen Wert wird, wird es als a> b falsch eingeschätzt, aber wenn a-b> 0 (abhängig vom Überlaufgrad), ist es in Ordnung. 』
Selbst wenn ein * 1,5 überläuft und negativ wird, liegt er im 32-Bit-Bereich, wenn dies als vorzeichenlos betrachtet wird. Daher kann der Überlauf durch * 1,5- (IntMax-8)> 0 bestimmt werden.
Obwohl es in der ByteArrayOutputStream-Klasse verdoppelt wird, ist der Maximalwert unmittelbar davor a = IntMax-8, also a * 2 = 2 * IntMax-16, und es wird mit a * 2- (IntMax-8) = IntMax-8> 0 beurteilt. es kann. Wenn jedoch a = IntMax, 2 * a- (IntMax-8) = IntMax + 8 <0 ist und das Urteil möglicherweise verfehlt wird. Möglicherweise liegt jedoch kein Problem vor, da das IntMax-Array nicht mit der aktuellen Java-VM gesichert werden kann. (Siehe unten)
"L.244 Ich weiß nicht warum es 8 ist. 』
Eigentlich habe ich mich gefragt, ob ich ein Array bis zu IntMax sichern könnte, aber die Sprachspezifikation ist bis zu IntMax, aber es scheint, dass es weniger VM-Implementierungen als diese gibt. Zum Beispiel in Oracle VM gemäß Maximale Anzahl von Array-Elementen in Java
32bit VM: 0x3fffffff - 3 (= 1,073,741,820)
64bit VM: 0x7fffffff - 2 (= 2,147,483,645)
Es scheint so.
Darüber hinaus gibt es bei ByteArrayOutputStream den Fehler, dass sogar 64-Bit-VMs nur bis zu etwa 0x3ffffffff verwendet werden können, und es scheint, dass dies behoben wurde. In Java SE 8 Update 31 wurde die Größenbeschränkung von ByteArrayOutputStream erhöht Vor der Korrektur wurde es beim Überlaufen auf IntMax gesetzt, dann wird es zu OutOfMemory, sodass es auf IntMax-8 gesetzt wird. IntMax-2 ist in Ordnung, wenn man nur Oracle VM betrachtet, aber es funktioniert wahrscheinlich nicht mit anderen Java VMs. Da die Quelle mit der enormen Kapazität von ArrayList identisch ist, scheint ArrayList auch zu diesem Zeitpunkt festgelegt zu sein.
Laut Array kann nicht mit Integer.MAX_VALUE-Elementen zugeordnet werden war es außerdem möglich, IntMax in JDK 6, IntMax in JDK 7 und JDK 8 zu sichern. Es gibt einen Fehlerbericht, der besagt, dass nur bis zu -2 gesichert werden können (es ist ein Dämon). "Das Schließen dieses Fehlers wird nicht behoben, da der aktuelle Code wie vorgesehen funktioniert." Ja, ich werde ihn nicht beheben. Es scheint, dass IntMax-headerSize (8 Byte) die Grenze für die Bequemlichkeit von GC ist. Warum ist IntMax-2 dann in Ordnung? was auch immer.
"Warum geben Sie Integer.MAX_VALUE hier zurück, während Sie in L.244 Integer.MAX_VALUE --8 sagen? 』
Auf jeden Fall lustig. Da IntMax-8 die Obergrenze ist, ist es meiner Meinung nach natürlicher, OutOfMemory zu werfen, wenn es diese überschreitet. Wenn Sie IntMax zurückgeben, sollte es danach OutOfMemory in Arrays.copyOf sein, aber es ist ein bisschen seltsam.
"Es ist bisher nicht möglich, minCapcity aufzurufen. Ich weiß nicht, was für einen Fall ich annehme. 』
Nein, ich denke, es gibt einige negative Bedingungen.
Beim Aufruf von public void sureCapacity (int minCapacity) {wird eine negative Prüfung durchgeführt.
Es gibt keine negative Prüfung für minCapacity, wenn aus der privaten Leere aufgerufen wird. EnecineCapacityInternal (int minCapacity) {. Mit anderen Worten, wenn es von add oder addAll kommt.
Die aktuelle elementData.length ist 0x60000000, und wenn sie mit 1,5 multipliziert wird, wird sie zu 0x90000000 und läuft über. Wenn Sie andererseits eine Liste von 0x60000000 an addAll übergeben, wird minCapacity zu 0xC0000000 und läuft über.
In diesem Moment, if (minCapacity - elementData.length > 0) if (newCapacity - minCapacity < 0) if (newCapacity - MAX_ARRAY_SIZE > 0) Sind alle wahr und riesige Kapazität ist negativ.
Separat if (newCapacity - minCapacity < 0) Es ist nicht erforderlich, auf true zu setzen, daher ist es ausreichend, wenn es durch Multiplikation mit 1,5 überläuft und minCapacity überläuft. Dies gilt auch dann, wenn addAll of List von 0x20000000 zu elementData.length 0x60000000 ist.
Ich fragte mich, warum die Obergrenze von IntMax-8 lag, daher war dies eine gute Gelegenheit, dies zu untersuchen. Als nächstes wird ArrayDeque empfohlen.
Recommended Posts