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
Marmite - Siema, napisałem sobie program w Javie i wygląda na to, że mam gdzieś wycie...

źródło: comment_b8EDnNvxj6Gj0Xsz7tkcDPamiFvSl7wh.jpg

Pobierz
  • 16
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

@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.
  • Odpowiedz
@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
  • Odpowiedz
@Marmite: Ale po każdym wywołaniu zwracasz tablicę stringów więc nie wiemy co z tymi stringami później robisz. Jeśli nie kończy się cykl życia zmiennych w których to przechowujesz to po prostu to wszystko będzie leżało na heapie
  • Odpowiedz
@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) {
  • Odpowiedz
@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
  • Odpowiedz
@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ć.
  • Odpowiedz
@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
  • Odpowiedz
@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?
  • Odpowiedz
@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
  • Odpowiedz