Ostatnio napotkałem ten błąd w mojej aplikacji internetowej:
java.lang.OutOfMemoryError: Przestrzeń PermGen
Jest to typowa aplikacja Hibernate / JPA + IceFaces / JSF działająca na Tomcat 6 i JDK 1.6. Najwyraźniej może się to zdarzyć po kilkukrotnym ponownym wdrożeniu aplikacji.
Co go powoduje i co można zrobić, aby tego uniknąć? Jak rozwiązać problem?
Odpowiedzi:
Rozwiązaniem było dodanie tych flag do wiersza poleceń JVM podczas uruchamiania Tomcat:
Możesz to zrobić, zamykając usługę tomcat, a następnie przechodząc do katalogu Tomcat / bin i uruchamiając tomcat6w.exe. Na karcie „Java” dodaj argumenty do pola „Opcje Java”. Kliknij „OK”, a następnie uruchom ponownie usługę.
Jeśli pojawi się błąd, określona usługa nie istnieje jako usługa zainstalowana , należy uruchomić:
gdzie nazwa_usługi to nazwa serwera wyświetlana w services.msc
Źródło: komentarz orx do zwinnych odpowiedzi Erica .
źródło
Lepiej spróbuj
-XX:MaxPermSize=128M
niż-XX:MaxPermGen=128M
.Nie umiem dokładnie określić wykorzystania tej puli pamięci, ale ma to związek z liczbą klas załadowanych do JVM. (W ten sposób włączenie odciążania klas dla tomcat może rozwiązać problem.) Jeśli twoje aplikacje generują i kompilują klasy w trakcie pracy, bardziej prawdopodobne jest, że potrzebna będzie pula pamięci większa niż domyślna.
źródło
Błędy PermGen serwera aplikacji, które występują po wielu wdrożeniach, są najprawdopodobniej spowodowane odwołaniami przechowywanymi przez kontener w modułach ładujących klasy starych aplikacji. Na przykład użycie niestandardowej klasy poziomu dziennika spowoduje, że odwołania będą przechowywane przez moduł ładujący klasy serwera aplikacji. Możesz wykryć te wycieki międzyklasowe za pomocą nowoczesnych narzędzi analitycznych JVM (JDK6 +), takich jak jmap i jhat, aby sprawdzić, które klasy są nadal przechowywane w Twojej aplikacji, oraz przeprojektowując lub eliminując ich użycie. Zwykłymi podejrzanymi są bazy danych, rejestratory i inne biblioteki na poziomie podstawowej struktury.
Zobacz wycieki Classloader: przerażający wyjątek „java.lang.OutOfMemoryError: PermGen space” , a zwłaszcza jego post uzupełniający .
źródło
Powszechnymi błędami, jakie popełniają ludzie, są zdania, że przestrzeń sterty i przestrzeń permgena są takie same, co wcale nie jest prawdą. Na stosie może pozostać dużo miejsca, ale wciąż może zabraknąć pamięci w permgen.
Typowe przyczyny OutofMemory w PermGen to ClassLoader. Za każdym razem, gdy klasa jest ładowana do JVM, wszystkie jej metadane, wraz z Classloaderem, są przechowywane w obszarze PermGen i będą one usuwane, gdy Classloader, który je załadował, jest gotowy do odśmiecania. W przypadku, gdy Classloader ma wyciek pamięci, wszystkie załadowane przez niego klasy pozostaną w pamięci i spowodują utratę pamięci PermGen, gdy powtórzysz ją kilka razy. Klasycznym przykładem jest Java.lang.OutOfMemoryError: PermGen Space w Tomcat .
Teraz są dwa sposoby rozwiązania tego:
1. Znajdź przyczynę wycieku pamięci lub w przypadku wycieku pamięci.
2. Zwiększ rozmiar PermGen Space za pomocą parametrów JVM
-XX:MaxPermSize
i-XX:PermSize
.Możesz również sprawdzić 2 Rozwiązanie Java.lang.OutOfMemoryError w Javie, aby uzyskać więcej informacji.
źródło
-XX:MaxPermSize and -XX:PermSize
?? Nie mogę znaleźćcatalina.bat
. Moja wersja tomcat to5.5.26
.Użyj parametru wiersza polecenia
-XX:MaxPermSize=128m
dla Sun JVM (oczywiście zastępując 128 dowolnym potrzebnym rozmiarem).źródło
Spróbuj,
-XX:MaxPermSize=256m
a jeśli będzie się powtarzał, spróbuj-XX:MaxPermSize=512m
źródło
XX:MaxPermSize=1024m
:)I dodał
-XX: MaxPermSize = 128m
(można eksperymentować, które działa najlepiej) do Argumenty VM jako Używam Eclipse IDE. W większości JVM domyślny rozmiar PermSize to około 64 MB, co kończy się brakiem pamięci, jeśli w projekcie jest zbyt wiele klas lub ogromna liczba ciągów.W przypadku zaćmienia opisano to również w odpowiedzi .
KROK 1 : Kliknij dwukrotnie serwer tomcat na karcie Serwery
KROK 2 : Otwórz Conf konf. I dodaj
-XX: MaxPermSize = 128m
do końca istniejących argumentów VM .źródło
Odwracam głowę od tego problemu podczas wdrażania i cofania również złożonej aplikacji internetowej i pomyślałem, że dodam wyjaśnienie i moje rozwiązanie.
Kiedy wdrażam aplikację na Apache Tomcat, tworzony jest nowy ClassLoader dla tej aplikacji. ClassLoader jest następnie używany do ładowania wszystkich klas aplikacji, a po cofnięciu wszystko powinno ładnie zniknąć. Jednak w rzeczywistości nie jest to takie proste.
Jedna lub więcej klas utworzonych podczas życia aplikacji internetowej zawiera odwołanie statyczne, które gdzieś wzdłuż linii odwołuje się do ClassLoadera. Ponieważ referencja jest pierwotnie statyczna, żadna ilość czyszczenia pamięci nie wyczyści tej referencji - ClassLoader i wszystkie klasy, które są ładowane, pozostaną.
Po kilku ponownych wdrożeniach napotykamy błąd OutOfMemoryError.
Teraz stało się to dość poważnym problemem. Mogłem się upewnić, że Tomcat zostanie zrestartowany po każdym ponownym wdrożeniu, ale spowoduje to usunięcie całego serwera, a nie tylko aplikacji, co często nie jest możliwe.
Zamiast tego stworzyłem rozwiązanie w kodzie, które działa na Apache Tomcat 6.0. Nie testowałem na żadnym innym serwerze aplikacji i muszę podkreślić, że prawdopodobnie nie zadziała to bez modyfikacji na żadnym innym serwerze aplikacji .
Chciałbym również powiedzieć, że osobiście nienawidzę tego kodu, i że nikt nie powinien używać go jako „szybkiej poprawki”, jeśli istniejący kod można zmienić w celu użycia odpowiednich metod zamykania i czyszczenia . Należy go użyć tylko wtedy, gdy istnieje biblioteka zewnętrzna, od której zależy Twój kod (w moim przypadku był to klient RADIUS), który nie zapewnia możliwości czyszczenia własnych odniesień statycznych.
W każdym razie, dalej z kodem. Powinno to zostać wywołane w miejscu, w którym aplikacja się wdraża - na przykład metoda zniszczenia serwletu lub (lepsze podejście) metoda kontekstDestroyed ServletContextListener.
źródło
Komunikat
java.lang.OutOfMemoryError: PermGen
kosmiczny wskazuje, że obszar pamięci stałej generacji jest wyczerpany.Wszelkie aplikacje Java mogą używać ograniczonej ilości pamięci. Dokładna ilość pamięci, której może użyć konkretna aplikacja, jest określona podczas uruchamiania aplikacji.
Pamięć Java jest podzielona na różne regiony, które można zobaczyć na poniższym obrazie:
Metaspace: rodzi się nowa przestrzeń pamięci
JVK JDK 8 HotSpot wykorzystuje teraz pamięć natywną do reprezentacji metadanych klasy i nazywa się Metaspace; podobny do Oracle JRockit i IBM JVM's.
Dobrą wiadomością jest to, że oznacza to, że nie będzie już więcej
java.lang.OutOfMemoryError: PermGen
problemów z przestrzenią i nie będzie już konieczne dostrajanie i monitorowanie tej przestrzeni pamięci za pomocą Java_8_Download lub wyższej.źródło
1) Zwiększanie wielkości pamięci PermGen
Pierwszą rzeczą, jaką można zrobić, jest zwiększenie wielkości powierzchni sterty stałej generacji. Nie można tego zrobić przy użyciu zwykłych argumentów JVM –Xms (ustaw początkowy rozmiar sterty) i –Xmx (ustaw maksymalny rozmiar sterty), ponieważ, jak wspomniano, przestrzeń sterty stałej generacji jest całkowicie oddzielna od zwykłej przestrzeni sterty Java, a te argumenty są ustawione przestrzeń dla tej zwykłej przestrzeni sterty Java. Istnieją jednak podobne argumenty, których można użyć (przynajmniej w przypadku Jvms Sun / OpenJDK), aby zwiększyć rozmiar sterty generacji stałej:
Domyślnie 64m.
2) Włącz zamiatanie
Innym sposobem na zadbanie o to na dobre jest umożliwienie rozładowania klas, aby Twój PermGen nigdy się nie kończył:
Takie rzeczy w przeszłości działały na mnie magicznie. Jedną rzeczą jest jednak znaczna kompromis w wydajności korzystania z nich, ponieważ przemiatanie permgenem wykona dodatkowe 2 żądania dla każdego twojego żądania lub coś podobnego. Musisz zrównoważyć swoje wykorzystanie z kompromisami.
Szczegóły tego błędu można znaleźć.
http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html
źródło
Alternatywnie możesz przełączyć na JRockit, który obsługuje permgen inaczej niż jvm firmy Sun. Ogólnie ma również lepszą wydajność.
http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
źródło
java.lang.OutOfMemoryError: There is insufficient native memory
tego dostaniesz .Miałem problem, o którym tu mówimy, mój scenariusz to eclipse-helios + tomcat + jsf, a to, co robiłeś, polega na stworzeniu prostej aplikacji do tomcat. Pokazałem tutaj ten sam problem, rozwiązałem go w następujący sposób.
W Eclipse przejdź do zakładki serwery, kliknij dwukrotnie zarejestrowany serwer w moim przypadku tomcat 7.0, otwiera mój serwer plików Ogólne informacje rejestracyjne. W sekcji „Informacje ogólne” kliknij link „Otwórz konfigurację uruchamiania” , otwiera to wykonanie opcji serwera na karcie Argumenty w argumentach VM dodanych na końcu te dwa wpisy
i gotowy.
źródło
Najprostszą odpowiedzią jest obecnie użycie Java 8.
Nie rezerwuje już pamięci wyłącznie na przestrzeń PermGen, pozwalając na połączenie pamięci PermGen ze zwykłą pulą pamięci.
Pamiętaj, że będziesz musiał usunąć wszystkie niestandardowe
-XXPermGen...=...
parametry uruchamiania JVM, jeśli nie chcesz, aby Java 8 narzekało, że nic nie robią.źródło
W polu tekstowym Opcje Java dodaj ten wiersz:
źródło
Błąd przestrzeni perm gen występuje z powodu użycia dużej przestrzeni zamiast przestrzeni przewidzianej przez JVM do wykonania kodu.
Najlepszym rozwiązaniem tego problemu w systemach operacyjnych UNIX jest zmiana konfiguracji w pliku bash. Poniższe kroki rozwiązują problem.
Uruchom polecenie
gedit .bashrc
na terminalu.Utwórz
JAVA_OTPS
zmienną o następującej wartości:Zapisz plik bash. Uruchom polecenie exec bash na terminalu. Uruchom ponownie serwer.
Mam nadzieję, że to podejście zadziała w przypadku twojego problemu. Jeśli używasz wersji Java niższej niż 8, ten problem występuje czasami. Ale jeśli używasz Java 8, problem nigdy nie występuje.
źródło
Zwiększenie wielkości stałej generacji lub poprawienie parametrów GC NIE pomoże, jeśli masz prawdziwy wyciek pamięci. Jeśli używana aplikacja lub biblioteka innej firmy używa, nieszczelne moduły ładujące, jedynym prawdziwym i trwałym rozwiązaniem jest znalezienie tego wycieku i usunięcie go. Istnieje wiele narzędzi, które mogą ci pomóc, jednym z najnowszych jest Plumbr , który właśnie wydał nową wersję z wymaganymi możliwościami.
źródło
Również jeśli używasz log4j w swojej aplikacji internetowej, sprawdź ten akapit w dokumentacji log4j .
Wygląda na to, że jeśli korzystasz
PropertyConfigurator.configureAndWatch("log4j.properties")
, powoduje to wycieki pamięci podczas cofania aplikacji internetowej.źródło
Mam kombinację Hibernacji + Eclipse RCP, próbowałem użyć
-XX:MaxPermSize=512m
i-XX:PermSize=512m
wydaje się, że działa dla mnie.źródło
Set
-XX:PermSize=64m -XX:MaxPermSize=128m
. Później możesz również spróbować zwiększyćMaxPermSize
. Mam nadzieję, że to zadziała. To samo działa dla mnie. Ustawienie tylkoMaxPermSize
mi nie działało.źródło
Próbowałem kilku odpowiedzi i jedyną rzeczą, która ostatecznie wykonała to zadanie, była konfiguracja wtyczki kompilatora w pom:
mam nadzieję, że to pomoże.
źródło
jrockitrozwiązałem to również dla mnie; Zauważyłem jednak, że czasy restartu serwletów były znacznie gorsze, więc chociaż był lepszy w produkcji, był nieco trudny w rozwoju.
źródło
Konfiguracja pamięci zależy od charakteru aplikacji.
Co robisz?
Jaka jest liczba transakcji?
Ile danych ładujesz?
itp.
itp.
itp
Prawdopodobnie możesz profilować aplikację i rozpocząć czyszczenie niektórych modułów z aplikacji.
Tomcat wdrożył na gorąco, ale zużywa pamięć. Spróbuj ponownie uruchomić pojemnik raz na jakiś czas. Będziesz także musiał znać ilość pamięci potrzebną do uruchomienia w trybie produkcyjnym, wydaje się, że to dobry czas na te badania.
źródło
Mówią, że najnowsza wersja Tomcat (6.0.28 lub 6.0.29) znacznie lepiej radzi sobie z ponownym wdrażaniem serwletów .
źródło
Napotkałem dokładnie ten sam problem, ale niestety żadne z zaproponowanych rozwiązań nie zadziałało. Problem nie wystąpił podczas wdrażania, a ja nie robiłem żadnych gorących wdrożeń.
W moim przypadku problem pojawiał się za każdym razem w tym samym momencie podczas uruchamiania mojej aplikacji internetowej, podczas łączenia (przez hibernację) z bazą danych.
Ten link (wspomniany również wcześniej) zawierał wystarczającą liczbę elementów wewnętrznych, aby rozwiązać problem. Przeniesienie jdbc- (mysql) -driver z WEB-INF do folderu jre / lib / ext / wydaje się rozwiązać problem. To nie jest idealne rozwiązanie, ponieważ aktualizacja do nowszej wersji JRE wymaga ponownej instalacji sterownika. Kolejnym kandydatem, który może powodować podobne problemy, jest log4j, więc możesz również chcieć go przenieść
źródło
Pierwszym krokiem w takim przypadku jest sprawdzenie, czy GC może zwolnić klasy z PermGen. Standardowa JVM jest pod tym względem raczej konserwatywna - klasy rodzą się, aby żyć wiecznie. Po załadowaniu klasy pozostają w pamięci, nawet jeśli żaden kod ich już nie używa. Może to stać się problemem, gdy aplikacja tworzy dynamicznie wiele klas, a generowane klasy nie są potrzebne przez dłuższy czas. W takim przypadku pomocne może być zwolnienie przez JVM definicji klas. Można to osiągnąć, dodając tylko jeden parametr konfiguracyjny do skryptów uruchamiania:
Domyślnie jest ustawiony na false, więc aby to włączyć, musisz jawnie ustawić następującą opcję w opcjach Java. Jeśli włączysz CMSClassUnloadingEnabled, GC przeczesuje również PermGen i usunie klasy, które nie są już używane. Pamiętaj, że ta opcja będzie działać tylko wtedy, gdy UseConcMarkSweepGC jest również włączony przy użyciu poniższej opcji. Dlatego podczas uruchamiania ParallelGC lub, na wszelki wypadek, Serial GC, upewnij się, że ustawiłeś GC na CMS, określając:
źródło
Przypisanie większej ilości pamięci Tomcat NIE jest właściwym rozwiązaniem.
Prawidłowym rozwiązaniem jest przeprowadzenie czyszczenia po zniszczeniu i odtworzeniu kontekstu (wdrożenie na gorąco). Rozwiązaniem jest powstrzymanie wycieków pamięci.
Jeśli serwer Tomcat / Webapp informuje cię, że nie można wyrejestrować sterowników (JDBC), to wyrejestruj je. To zatrzyma wycieki pamięci.
Możesz utworzyć ServletContextListener i skonfigurować go w pliku web.xml. Oto przykładowy ServletContextListener:
I tutaj możesz go skonfigurować w pliku web.xml:
źródło
„Oni” są w błędzie, ponieważ korzystam z wersji 6.0.29 i mam ten sam problem, nawet po ustawieniu wszystkich opcji. Jak powiedział Tim Howland powyżej, te opcje odkładają tylko nieuniknione. Pozwalają mi ponownie wdrożyć 3 razy, zanim trafię w błąd, a nie za każdym razem, gdy dokonam ponownego wdrożenia.
źródło
W przypadku, gdy są coraz to w IDE Eclipse, nawet po ustawieniu parametrów
--launcher.XXMaxPermSize
,-XX:MaxPermSize
itp, nadal jeśli otrzymujesz ten sam błąd, to najbardziej prawdopodobne jest to, że Eclipse jest za pomocą wersji buggy środowiska JRE, które zostały zainstalowane przez niektóre aplikacje innych firm i ustawione na domyślne. Te błędne wersje nie pobierają parametrów PermSize, więc bez względu na to, co ustawisz, nadal występują te błędy pamięci. Zatem w swoim eclipse.ini dodaj następujące parametry:Upewnij się również, że ustawiłeś domyślne środowisko JRE w preferencjach w zaćmieniu na prawidłową wersję Java.
źródło
Jedynym sposobem, który działał dla mnie, był JRockit JVM. Mam MyEclipse 8.6.
Sterta JVM przechowuje wszystkie obiekty wygenerowane przez działający program Java. Java używa
new
operatora do tworzenia obiektów, a pamięć na nowe obiekty jest przydzielana na stercie w czasie wykonywania. Wyrzucanie elementów bezużytecznych to mechanizm automatycznego zwalniania pamięci zawartej w obiektach, do których program nie odwołuje się.źródło
Miałem podobny problem. Mój to projekt oparty na wstrzykiwaniu zależności JDK 7 + Maven 3.0.2 + Struts 2.0 + Google GUICE.
Ilekroć próbowałem uruchomić
mvn clean package
polecenie, pojawiał się następujący błąd i pojawiał się komunikat „BUILD FAILURE”Wypróbowałem wszystkie powyższe przydatne porady i wskazówki, ale niestety żadna z nich nie zadziałała. To, co zadziałało, zostało opisane krok po kroku poniżej: =>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
element, a następnie<argLine>
element podrzędny, w którym przekaż,-Xmx512m -XX:MaxPermSize=256m
jak pokazano poniżej =><configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>
Mam nadzieję, że to pomoże, miłego programowania :)
źródło