Wpis z mikrobloga

Siema, napisałem sobie program w Javie i wygląda na to, że mam gdzieś wyciek pamięci, przynajmniej obserwując wskazania profilera widzę że zajętość stosu rośnie w miarę jak program sobie liczy. Posługując się tym artykułem zidentyfikowałem sobie kilka miejsc, które teoretycznie mogą być winne (o dziwo wszystkie zawierają lambdy). Screenshot z przykładową metodą w pic relu. Kod tej metody wygląda tak:
http://pastebin.com/yQBDEzwX
Przyznam się bez bicia - nie znam się na tym co w Javie siedzi pod maską, ale gdzie tu może być wyciek? No chyba że błędnie zinterpretowałem tego screena, no ale liczba generacji faktycznie wydaje się zbyt duża.
#java #programowanie
Pobierz Marmite - Siema, napisałem sobie program w Javie i wygląda na to, że mam gdzieś wycie...
źródło: comment_b8EDnNvxj6Gj0Xsz7tkcDPamiFvSl7wh.jpg
  • 16
@Marmite: której javy używasz? był kiedyś problem (chyba naprawiony w którymś updacie do javy 7) z substringiem, który kopiował i trzymał referencję do tablicy char[] z całym stringiem co przy długich stringach powodowało memory leak.

edit: a nie przecież lambdy są więc java8

Przy takim kodzie raczej wycieku nie powinno być choć nie widać co się dzieje w całym programie.
@hesar: A co mi to da, kiedy otrzymam ciąg w którym będzie np. 10 spacji? Parametr nie będzie pusty, a też nie muszę robić na nim żadnych operacji.
@Legol: Spróbuję tę i inne metody które teoretycznie wyciekają przepisać na wersję bez lambd, bo to mój jedyny pomysł. Natomiast nie wiem czy wiedza co dzieje się w pozostałych częściach programu jest akurat w tym wypadku potrzebna - wg allocation stack trace
@Marmite: tworzysz mase obiektow i trzymasz je w funkcji main. To czy masz leak sprawdzisz jak pole generations bedzie caly czas roslo jak np progam pochodzi przez pare minut.

na szybko: tak chyba mozesz zastapic funkcje

private static String[] splitTextToLowercaseWords(String text) {
return Arrays.stream(text.trim().split("\W+"))
.filter(String::isEmpty)
.map(String::toLowerCase)
.toArray(String[]::new);
}

PS. tutaj nie masz leaka w tych funkcjach bo generations w main = generations az do subsequence (a tam raczej leak'a nie ma
@Legol: > który kopiował i trzymał referencję do tablicy char[] z całym stringiem co przy długich stringach powodowało memory leak

w jdk6 tak bylo, jdk7 juz jest tworzony nowy string z kazdym razem
@Legol: @afe1: Mądrze prawicie, koledzy. Przyjrzę się jeszcze cyklowi życia tych zmiennych, natomiast jestem póki co na 90% pewien, że te stringi powinny zostać "stracone" na etapie funkcji wdc.DifficultyClassificator.classifyWords (String[], int, double, double) - main nigdy ich nie powinna dostać.
@Marmite: Nie zwracaj pustych nowych array, lepiej mieć gdzieś stałą, public static final String[] empty = new String[0];
Męczysz tylko niepotrzebnie GC.

możesz też zmienić splitowanie, tak by używać klasy Pattern, inaczej java też za każdym wywołaniem sama tworzy nowy Pattern bla bla bla.

Ah, i używaj string.isEmpty() zamiast .equals(""), i w tym kodzie nawet nie wiem po co to sprawdzasz :D
@Marmite wycieki nie biorą się z alokacji dużej ilości danych tylko z nie zwalniania tych niepotrzebnych. Myślę ze kod który podałeś jest ok, ale co się potem dzieje z tą arrayka?
@GotoFinal: Nie wiem czemu nie dostałem powiadomienia do tego posta. Niby mógłbym mieć gdzieś takie pole, ale jakbym chciał to wykonać dla wszystkich pozostałych funkcji w kodzie, to liczba pól by mi trochę urosła.
@moriturius: Jest przekazywana wyżej aż, w końcu trafia do funkcji, z której do main() jest już zwracane zupełnie co innego - więc teoretycznie powinna umrzeć. Wygląda na to, że jednak źle zinterpretowałem informacje z profilera, przynajmniej