Debugging v praxi - opravdu samozřejmost?!

V poslední době jsem zjistil, že některé věci, které já považuji za samozřejmé, pokud se rozhlédnu kolem sebe, tak úplně samozřejmé nejsou. Jednou z nich je debugování Javovského kódu. I v dnešní době, kdy je podpora ze strany technologií na perfektní úrovni je mnoho vývojářů, kteří pro rutinní vývoj (nemluvím o řešení problémů po nasazení aplikace) a odlaďování kódu debuggování nepoužívají a spoléhají se na záznamy z logu. Je pravda, že tento přístup má své výhody – obvykle se tímto způsobem obohatí kód dostatečným množstvím logů, že i v produkci je obvykle dost informací k řešení problémů, pokud nastanou. Zásadní nevýhodou, kterou v tom spatřuji já je naprosto drastické snížení produktivity programování. Problém, který se dá vyřešit během půl minuty vložením breakpointu na správné místo v kódu se může v případě procházení logů protáhnout klidně i na pět minut. Flow programátora je potom – však vy víte kde :).

Proto tento článek věnuji těm, kteří debugging nepoužívají nebo měli nějaké problémy s jeho zprovozněním.

JVM se pro ladění spouští ve speciálním režimu (tzn. se speciálními parametry), aby bylo možné jeho chod ovlivňovat. V debug režimu bude Java pravděpodobně o dost pomalejší, takže tyto parametry si dovolte použít pouze na vývojovém prostředí.

Pro spuštění Javy v debug módu stačí do parametrů spuštění přidat následující parametry (je navíc třeba zajistit, že se vám volá java z instalace SDK a ne pouze standardního JRE):


-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

Kde jednotlivé parametry znamenají zhruba následující:

  • -Xdebug
    zapíná podporu pro debugování v JVM
  • -Xnoagent
    vypíná "starou" verzi java debuggeru
  • -Djava.compiler
    vypíná JIT (just in time) compiler - tedy HotSpot optimalizaci (logicky usuzuji, že pokud by zůstala zapnuta, mohly by díky optimalizaci některé řádky prostě vyzmizet, což pro debugging není úplně optimální - nicméně dle tohoto záznamu v Sun fóru, by to zas až tak veliký problém být neměl - ašak nejsem odborník, abych mohl polemizovat)
  • -Xrunjdwp
    nahrává knihovny pro debugging a stanovuje druh přenosu
    • transport: typ přenosu - v podstatě existují dva:
      1. dt_socket: připojení přes socket - vyžaduje nastavení portu
      2. dt_shmem: připojení přes sdílenou paměť (pouze pro MS Windows platformu) - vyžaduje nastavení názvu
    • server: stanovuje, která strana (JVM nebo debugovací klient) je tou aktivní stranou - pokud server=y - JVM čeká až se klient aktivní připojí k serveru, v opačném případě se JVM okamžitě zkusí připojit k debugovacímu klientovi na stanovené adrese (paramtr address)
    • suspend: má smysl dávat asi jen "y" - zajistí, že JVM pozastaví výkon všech vláken v případě, že dojde k debugovací události
    • address: v případě použití dt_socket by se zde mělo zadat číslo portu, kde bude JVM naslouchat na připojení debug klienta
    • name: v případě použití dt_shmem stanovuje název úseku sdílené paměti (ale radši si to ověřte, tady si nejsem moc jistý)

V podstatě je pouze důležité abyste potom v IDE nastavili také stejné parametry (důležitá je hlavně adresa = port a transportní režim - doporučuji socket). K takto spuštěnému JVM se potom můžete odkudkoli připojit a debugovat jeho kód. Je klidně možné takto debugovat i kód na serveru, který fyzicky leží úplně na jiném místě – jen si musíte dát pozor, aby firewally propustily komunikaci na portu, který je otevřen pro debugging (také je komunikace odpovídajícím způsobem zpomalená, takže debugování není tak plynulé).

Toto je obecný způsob nastavení javy pro debugování – lze použít jak pro debugování webových aplikací uvnitř web kontejnerů, pro klientské aplikace a můžete tím klidně krokovat i zdrojáky Javy samotné nebo třebas i zdrojáky aplikačních serverů, pokud je máte k dispozici (a věřte mi tímhle způsobem se můžete do jejich fungování dostat daleko rychleji než pasivním studiem kódu).
Ukažme si nyní spuštění javy v debugging režimu při použití web kontejneru Tomcat 5.0 a Javy 1.4.2 a pokus o odkrokování jednoduché webové aplikace (jednoduchého servletu).

AVI ukázka remote debuggingu v prostředí IntelliJ IDEA 6.0.4


AVI ukázka remote debuggingu v prostředí NetBeans 6.0 m8


Tady je něco pro Eclipsisty od Dagiho


A tady je zajímavý příspěvek od Borůvka o HotSwap v prostředí Eclipse

Celé se to ještě dále zjednodušit. IDE mají obvykle v sobě přímou podporu pro základní webové či aplikační kontejnery a obvykle stačí jen vytvořit novou konfiguraci pro tyto kontejnery s uvedením cesty, kde je nainstalován a IDE se postará o vše ostatní.
Nicméně je vhodné znát procesy, které se stejně dějí na pozadí, aby to celé pro nás nebyla taková magie – znalost se hodí obvykle ve chvíli, kdy to celé nefunguje tak jak má.

Z mého pohledu je skvělou věcí HOT REDEPLOY funkcionalita, kterou poskytuje IDE (v IntelliJ IDEA je to velmi jednoduché – s Netbeansy, které jsem používal před půl rokem se mi to nějak nepovedlo rozchodit, možná je to tím, že NetBeansy pro buildování a deploy používají interně Anta, takže je pro ně obtížné zjistit, které třídy se změnily a provést HOT REDEPLOY pouze na nich). Stačí abyste měli Javu spuštěnou v debug režimu a při překompilování tříd / projektu Idea sama zjistí, které třídy se od posledního deploye změnily a podhodí je JVM k výměně. Ani nepotřebujete mít chod aplikace zastavený na nějakém breakpointu v dané třídě – stačí být jen „připojený“ k JVM. Tím se celé kolečko „nalezení problému – oprava – deploy – vyzkoušení opravy“ minimalizuje na opravdu jen pár vteřin a celý vývoj se může opravdu velmi urychlit. Zvláště pak v případech, kdy programátor nepoužívá k vývoji hlavní funkcionality automatické testy (tzn. je odkázán na ruční oklikání v testovacím prostředí) – což bohudík není můj případ ;).

Pozn. 27.5.2007: Tak jsem NetBeansům křivdil - v debug módu je prý v toolbaru k dispozici funkce "apply code changes", která by mělá právě HOT REDEPLOY provést.