poniedziałek, stycznia 22, 2024

Jak z metody size() w List w Java'ie dostać ujemną liczbę? ;-)

Chciałem dziś popsuć LinkedList, ale wychodzi na to, że mam za mało pamięci w komputerze ;-)

Popsucie miało wyglądać mniej więcej tak:

var list = new LinkedList<Integer>();
doMagic(list);
System.out.println(list.size()); // return negative number!!!

Gdzie doMagic miało wyglądać jakoś tak:

static void doMagic(LinkedList<Integer> l) {
for (var i=0L; i<Integer.MAX_VALUE+1000L; i++) {
l.add(Integer.valueOf(0));
}
}

No bo jeśli spojrzymy na implementację LinkedList to implementuje ona List, a List ma metodę size() która zwraca int, ale LinkedList nie ma ograniczenia na rozmiar innego niż pamięć, w samej metodzie linkLast(E e), która wołana jest z add(E e) mamy:

void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}

Co znaczy tyle, że jeśli mamy odpowiednio dużo pamięci to w pewnym momencie przekręcimy licznik ;-)

Czyli jakbyśmy zawołali size() to zwróci liczbę ujemną, ale jeśli policzymy wszystkie elementy kodem:

var count = 0L;
for (var n:list) {
count++;
}

To w count będziemy mieli 2147484647 ;-)
Co ciekawe zawołanie get(int) w takim przypadku wyrzuciłoby IndexOutOfBoundsException pokazując ujemną liczbę ;-)

Chyba znalazłem uzasadnienie dla kupienia Macbooka z M3 Max ;-) Bo chciałbym naprawdę sprawdzić czy to się tak zachowa ;-)

Inna sprawa ile byśmy potrzebowali RAMu żeby móc ten problem osiągnąć ;-) Tak jeden Node to powiedzmy między 48 a 64 bajty.... co daje dolną granicę najmniej 96 GB RAM ;-) ale podejrzewam, że tak naprawdę to by było jakieś 170 GB ;-)
Jeszcze chwilę potrwa nim będziemy mieli takie laptopy ;-) 
Największy Macbook Pro to teraz 128 GB RAM ;-)


[update]

I chyba nie muszę kupować takiej maszyny dużej ;-) bo nadal mogę ustawić rozmiar heapy na 150 GB ;-)

I wtedy gdy robię list.get(10) po dodaniu 2147484647 objektów to dostaję wyjątek:


A program w Activity Managerze ma 105 GB RAM przypisane ;-)

[next update ;-)]

Czyli wypisanie list.size() dało wynik -2147482649, ale już fragment:

var count = 0L;
for (var n:list) {
count++;
}

Nie zadziałał w ogóle, bo już w linii z for poleciał wyjątek ;-), okazuje się, że gdy jest produkowany iterator to wołany jest gdzieś w środku range check i ten wywala wyjątek dla Index: 0 ;-) 
Czyli LinkedList po przekręceniu licznika nie nadaje się nawet do iterowania ;-) ale co ciekawe można kasować elementy z przodu i tyłu aż nam wróci size do pozytywnych int'ów i można iterować ;-)



Podobne postybeta
Ile z obligacji... odsłona 2 ;-)
LinkedList w Java'ie to taki miś koala...
Po Devoxx&#39;ie
Ile w tym i przyszłym miesiącu z odsetek za obligacje?
Go dla Java'owca ;-) odcinek 2 "kontenery dwa ;-)"

Brak komentarzy:

Prześlij komentarz