4. diel - IntelliJ IDEA - Debugging
V minulej lekcii, IntelliJ IDEA - Scopes, Live Templates, Databáza, Pluginy , sme si ukázali Scopes, live templates, SQL Explorer a pluginy.
V dnešnom Java tutoriálu si vysvetlíme, ako debugovať Java aplikácie za pomocou IDE IntelliJ IDEA. Všetko si vyskúšame na jednoduchom príklade.
Debugging
Debugging je proces odstránenie chýb v programe, ktoré obvykle nie sú na prvý pohľad vidieť. Niekedy sa o ňom hovorí aj ako o "ladenie" programu.
Prečo a kedy debugovať?
Chyby v programe sa väčšinou prejavujú tým, že je v nejakej premennej nesprávna hodnota, ktorá potom zapríčiní nefunkčnosť programu. Určite ste sa už dostali do situácie, keď váš program nefungoval správne. Možno ste vykonávali nejaké zdĺhavé kontrolné výpisy rôznych premenných, aby ste zistili, kde je ešte všetko správne a kde sú už nesprávne hodnoty.
Chybu možno ale zvyčajne nájsť oveľa ľahšie pomocou debugovania. Program zvyčajne spustíme v špeciálnom režime, kde máme dovolené určité "cheaty", ako napr. Program pozastavovať a nazerať do obsahu premenných. Práve to sa dnes naučíme.
Nie je však pravda, že debugger používame len keď program nefunguje! Naopak, používame ho čo najviac to ide a to aj napríklad pre kontrolu správnosti na kritických miestach.
Príklad - Krokovanie cyklu
Majme jednoduchý cyklus, v ktorom budeme vypisovať čísla od
0
do 9
:
package onlineapp;
class Program
{
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println("Číslo: " + i);
}
}
}
Ako si môžete skúsiť, program funguje korektne. Napriek tomu si ho skúsime oddebugovat, než sa pustíme na nefunkčné kód.
Hraničnými
Breakpoint je základný stavebný kameň pri debugovania. Je to "bod" označujúce riadok, na ktorom sa program zastaví. Nám, ako programátorom, sa v tej chvíli zobrazí kompletná kontext programu, teda napr. Čo je v tej chvíli kde uložené. Pretože program stojí, môžeme si všetko ľahko skontrolovať.
Pridanie Breakpoint
Teraz sa naučíme vkladať hraničnými a zastavovať na nich program. V IntelliJ sa breakpoint na daný riadok vkladá kliknutím do priestoru vľavo vedľa čísla riadku. Breakpoint potom spoznáme podľa červeného kolieska. Vložme teda breakpoint na riadok, kde sa vypisuje číslo do konzoly:
Debug režim
Breakpoint máme pridaný. Keď však program teraz spustíme, nič zvláštneho sa nestane. Aby sa program naozaj zastavil, je potrebné ho spustiť v špeciálnom debugovacím režime. K tomu slúžia špeciálne tlačidlo vedľa tlačidla "Play":
Klikneme na tlačidlo pre debug. Program sa spustí a až narazí na náš breakpoint, tak sa zastaví:
Červený puntík označujúce breakpoint sa zmenil na zelený. To znamená, že breakpoint je dosiahnuteľný.
Záložka Debug
Otvorila sa nová záložka nazvaná Debug, ktorá obsahuje veľké množstvo informácií. Poďme si popísať, čo vidíme:
- časť ohraničená na obrázku vyššie zelene obsahuje zoznam všetkých aktuálne viditeľných premenných a ich hodnoty; hodnoty je možné zmeniť,
- oranžovo ohraničená časť obsahuje zásobník volaní všetkých funkcií, ktoré sa zavolali pred Breakpoint
Všimnite si, že IntelliJ sa snažia vkladať hodnoty premenných priamo do editora. V našom prípade vidíme priamo výpis hodnôt poľa.
Ďalej sú na obrázku zvýraznené dve časti ohraničené červeno.
Ovládanie programu a Breakpoint
V ľavej ohraničené červenej časti sa nachádza tlačidlá pre kontrolu ovládanie programu a Breakpoint:
- rerun 'Main' Ctrl + F5 - Ukončí aktuálny program a znova ho spustí,
- modify run configuration - Zobrazí nastavenia pre debug,
- resume program F9 - Uvoľní program z Breakpoint a nechá program bežať a prípadne sa zastaví o ďalšie breakpoint,
- pause program - Pozastaví vykonávanie vybraného vlákna - funguje podobne ako breakpoint, iba sa nezobrazia žiadne premenné,
- stop 'Main' Ctrl + F2 - Ukončí aktuálny program,
- view breakpoints Ctrl + Shift + F8 - pozrite si zoznam všetkých Breakpoint,
- mute breakpoints - potlačí všetky hraničnými; Keď program narazí na breakpoint v debug móde, breakpoint bude ignorovaný.
V druhej červeno ohraničené časti sa nachádza tlačidlá pre krokovanie programu. Pomocou krokovanie môžeme nechať program pokročiť na ďalší riadok a zas sa zastaviť:
- step over F8 (krok cez) - Vykonáme ďalší krok cez danú riadku s Breakpoint, na ktorej program aktuálne stoja. Ak sa na riadku volá funkcie, necháme ju len vykonať a potom prejdeme na ďalší riadok
- step into F7 (krok do) - Vykonáme ďalší krok "do" danej riadky. Robí to isté čo Step over až na rozdiel, že ak sa na riadku volá funkcie, prejdeme na prvý riadok vo funkcii
- force step into Alt + Shift + F7 (vynútený krok do) - Vynúti prechod do funkcie na riadku aj v prípade, že sa nejedná o našu metódu.
- step out Shift + F8 (krok von) - Pomocou kroku von vystúpime z aktuálne vykonávané funkcie
My sa nachádzame v cykle, kde iba vypisujeme jednu hodnotu. Keď sa pozrieme do výpisu konzoly, zatiaľ neuvidíme žiadny výpis (okrem možných hlášok od IDE).
Stlačením tlačidla krok cez sa vypíše do konzoly prvé
číslo a my sa v programe dostaneme na riadok s for
cyklom. Keď
tlačidlo stlačíme znovu, uvidíme, že sa inkrementovala pomocná premenná
i
z hodnoty 0
na hodnotu 1
. Týmto
spôsobom si môžeme odkrokovat celý cyklus:
Príklad - debugovania programu
Nakoniec si dáme príklad naozaj k precvičenie debugovania. Máme dva vnorené cykly, ktoré by mali vypísať malú násobilku:
package onlineapp;
class Program
{
public static void main(String[] args) {
for (int j = 1; j <= 10; j++) {
for (int i = 1; j <= 10; j++) {
System.out.print(i * j + "\t");
}
System.out.println();
}
}
}
Výsledok by mal vyzerať takto:
Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
Problém ale je, že sa vypíšu len čísla od 1
do
10
:
Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
Chybu budeme samozrejme chcieť nájsť a opraviť za pomoci Breakpoint a krokovanie. Aj keď uvidíte chybu na prvý pohľad, neotáľajte a tiež si to odkrokujte! V zložitejších aplikáciách chyba ľahko vidieť nebude a debugovania bude potrebné.
Postup riešenia
Očakávame, že vonkajšie cyklus sa vykoná 10x, zatiaľ čo vnútorná
cyklus sa vykoná celkom 100x. Vložíme breakpoint na riadok s
vonkajším for
cyklom:
for (int j = 1; j <= 10; j++) {
A spustíme program v debug režime. Bude nás zaujímať, ako sa premenné
i
a j
zvyšujú. Tlačidlom krok do
budeme postupne prechádzať cez oba cykly a pozorovať premenné i
a j
. Vonkajší cyklus pracuje s premennou j
, ktorá
by sa mala zmeniť iba 10x. Vnútorné cyklus pracuje s hodnotou i
,
ktorá by sa mala pri každej zmene j
upraviť 10x.
Postupným krokovaním však zistíme, že vnútorný cyklus inkrementuje
premennú j
namiesto i
. Vo vnútornom cyklu upravíme
j++
na i++
a program opäť spustíme v debug
režime:
for (int i = 1; j <= 10; i++)
Krokom opäť tlačidlom krok do. Sledujeme premennú
i
. Po čase začne nadobúdať neočakávaných hodnôt, ktoré sa
neustále o jednotku zvyšujú. Ak teraz necháte program bežať, začne sa
vám počítač kosiť. To je z dôvodu, že vo vnútornom cykle je podmienka,
ktorá nikdy nebude splnená.
V cykle for (int i = 1; j <= 10; i++)
máme premennú
i
, ktorú už správne inkrementuje, ale podmienka je zlá.
Premenná i
sa inkrementuje, kým platí j <= 10
.
Táto podmienka nikdy nebude splnená, pretože premenná j
sa
modifikuje len vo vonkajšom cykle. Opravíme podmienku vnútorného cyklu z
j <= 10
na i <= 10
a program už spustíme bez
Breakpoint:
package onlineapp;
class Program
{
public static void main(String[] args) {
for (int j = 1; j <= 10; j++) {
for (int i = 1; i <= 10; i++) {
System.out.print(i * j + "\t");
}
System.out.println();
}
}
}
Výsledkom už je očakávaná malá násobilka:
Konzolová aplikácia
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
V ďalšej lekcii, IntelliJ IDEA - Pokročilý debugging , si rozšírime znalosti debugovania v IntelliJ IDEA.