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'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