Tomcat a leaky

Při práci s Tomcatem jsme narazili na memory leaky. Tato chyba nastává při reloadu aplikace v Tomcatu. Nejčastěji se problém projevuje tak, že se zaplní část paměti heap a PermGen, která je použivaná pro načítané třídy (class).

Když tomcat načítá novou webovou aplikaci, uvolní všechny reference na původní ClassLoader a nechá GC, aby paměť uvolnil. Problém ovšem nastane, pokud na tento ClassLoader stále existuje reference. Pokud třída v rodičovském ClassLoaderu (např. část JDBC přímo v JDK) obsahuje odkaz na třídu v našem původním ClassLoaderu, a tím i přímo na na něj, nastane problém.

Problémy mohou způsobovat např. tyto knihovny:

  • JDBC DriverManager
  • Jasper (JSP compiler)
  • CGLIB – v nové verzi již opraveno

My jsme problém vyřešili tak, že v ostrém provozu Tomcat restartujeme a při vývoji jsme zvýšili paměť pro tomcat – -Xmx a
-XX:MaxPermSize=128m. Tím jsme minimalizovali riziko vzniku problému.

Více informací v článku Memory leak – classloader won’t let go.

3 thoughts on “Tomcat a leaky”

  1. Zajímavý článek.

    Mám jenom několik dodatků.

    1. Co se týká JBosse, tak tento problém existuje také. Takže není pravda, že problémy s integrovaným tomcatem nenastávají. (JBoss 4.0.3 SP1)
    2. Někde jsem četl, že problém PermGen způsobují statické instance tříd, které jsou používány ve webových aplikacích – toto ber jenom jako naznak dalšího možného zkoumání. Bylo doporučeno, co nejvíce knihoven nahrát do sdíleného knihovního adresáře tomcata – co nejméně do /WEB-INF/lib.

    Snad Ti to nějak pomůže.

  2. Ano, statické prvky to dělají. Ale statické prvky mimo /WEB-INF/lib. Takže jedno řešení je nahrát všechno mimo /WEB-INF/lib, ale i tak některé knihovny budou mít odkaz na objekty v tom waru (např. hibernate a mapované třídy).

    Pak je ještě řešení všechno naopak nahrát do /WEB-INF/lib. Ale stejně knihovny z JDK (např. JDBC DriverManager) jsou v původním classpath.

    Takže IMHO správným řešením je, aby tomcat uvolnil všechny co je v JDK a jary mít ve /WEB-INF/lib. Pokud ovšem přidáme do globální classpath něco co tomcat nezná a nemůže tak uvolnit, máme opět problémy. Proto mají některé wary různé uvolňovače.

    Čím více nad tím přemýšlím, tím více se mi zdá, že způsob jakým se v současné době izolují aplikace v kontejneru není zrovna nejlepší (a těmito slovy tedy potvrzuji tvrzení Arnošta, že se jedná o chybu architektury).

  3. Ještě jeden argument k tomu proč dávat vše mimo /WEB-INF/lib.

    Když už nastane leak a classloader se neuvolní (což je skoro vždy), samozřejmě pomůže, když v tomto classloaderu je tříd co nejméně (tím se zmenší velikost memory leaku).

Napsat komentář: Miloslav Vlach Zrušit odpověď na komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *