Cortiveo i GEngine - prirucnik

↑ Nazad

Nalaz 25. septembra 2026. Pitanje je bilo: „ne mogu da stavim breakpoint na atribut?" — može se, i to bez getera i setera.

1. Podrazumevani konstruktor — breakpoint radi

Kompajler uvek emituje <init> u bytecode, i kad ga nisi napisao. Zato <init> ima svoju Location i može da nosi breakpoint. Dokaz iz našeg traga (anonimna klasa, konstruktor nigde nije napisan):

io.cortiveo.sample.LegacyApp$Db$1.<init>()  LegacyApp.java:193

U Cortiveo tracerom:

cortiveo trace --app db.,gjava. --call db.tehnobiro.generator3.DataHPrint.<init> --args 3

Dve napomene:

2. Breakpoint na polju — postoji, i hvata direktan pristup

Ovo je pravi odgovor na zaobilazni put sa geterima/seterima. JDI ima watchpoint:

erm.createModificationWatchpointRequest(Field)   // UPIS
erm.createAccessWatchpointRequest(Field)         // CITANJE

Događaj (WatchpointEvent) nosi sve što treba:

metodašta daje
valueCurrent()stara vrednost
valueToBe()nova vrednost (samo kod upisa)
object()koja instanca (null za static)
location()fajl:linija koda koji je to uradio
thread()nit

U Cortiveo tracer je to ugrađeno (fddecc0):

cortiveo trace --app io.cortiveo. --field "io.cortiveo.sample.LegacyApp$InvoicePanel.*"
SET LegacyApp$InvoicePanel.confirm: null -> SpecialInvoiceButton@1205  na InvoicePanel@1204
    <- io.cortiveo.sample.LegacyApp$InvoicePanel.<init> LegacyApp.java:262
SET LegacyApp$InvoicePanel.table:   null -> JTable@1302  na InvoicePanel@1204
    <- io.cortiveo.sample.LegacyApp$InvoicePanel.<init> LegacyApp.java:263

Oba ta upisa su direktna — inicijalizatori polja, nijedan seter. Klasa.* prati sva polja klase, --fieldread prati čitanja.

Zašto je to bolje od getera/setera: JVM javlja pristup na nivou polja, pa se ne može promašiti ni jedno mesto. Tvoja zamerka na zaobilazni put je bila tačna: ako jedno direktno čitanje ostane, informacija se tiho gubi — a watchpoint nema tu rupu.

Cena: kao breakpoint — plaća se samo kad se polje dirne. Ali polje u vrućoj petlji košta kao MethodEntry, pa se ne stavlja na brojače i kursore.

Ograničenja: watchpoint je po polju, ne po objektu — pale se svi objekti te klase (filtriraj po object().uniqueID()). Provera podrške: canWatchFieldModification() / canWatchFieldAccess() (HotSpot podržava oba).

Ako ipak ideš putem getera/setera — proveri mašinski

Ne nadaj se da nisi promašio mesto, dokaži: bytecode nosi instrukcije putfield/getfield, pa

javap -c -p -cp app.jar db.tehnobiro.Obrazac | grep -E "(put|get)field.*Polje"

nađe svaki direktan pristup, uključujući onaj u klasama koje si zaboravio.

3. Isto pitanje u drugim jezicima

C / C++ — hardverski watchpoint

Ovo je izvorni dom pojma:

(gdb) watch  mojaPromenljiva     # prekid na UPIS
(gdb) rwatch mojaPromenljiva     # na CITANJE
(gdb) awatch mojaPromenljiva     # na oba
(lldb) watchpoint set variable mojaPromenljiva

Visual Studio isto ima Data Breakpoint. Mehanizam su debug registri procesora (x86: DR0–DR3), odakle i glavno ograničenje: najviše 4 watchpointa, svaki na 1/2/4/8 bajtova. Kad se pređe, debager pada na software watchpoint = izvršavanje korak-po-korak, sto puta sporije.

Druga zamka: watchpoint je na adresi. Ako se memorija oslobodi i realocira, watchpoint gleda u tuđe podatke. Za „ko je pisao po ovoj memoriji" tu su i AddressSanitizer, Valgrind/memcheck i rr (snimi izvršavanje, pa reverse-continue do upisa).

C# / .NET

Java — zaključak

Java je tu najbolje opremljena: watchpoint je na polju, ne na adresi, pa ga GC ne kvari, i nema ograničenja od 4 kao hardverski registri. Ono što u C/C++ mora u hardver, JVM daje kroz JDWP.

4. Kratka tablica „šta kad ne mogu da nađem gde se nešto dešava"

pitanjealat
ko kreira objekat--call Klasa.<init> (radi i za podrazumevani konstruktor)
koliko ih ima / ko ih držiinstanceCounts, ReferenceType.instances
ko menja polje--field Klasa.polje
ko čita polje--fieldread Klasa.polje
ko poziva metodu--call Klasa.metoda + lanac pozivalaca (--stack N)
šta je klik uradio--trigger actionPerformed + --args N
gde ode vreme--progress + === end click brojevi

Sve to važi i za kod bez izvora — dovoljan je bytecode sa debug informacijama (GTehnobiro ga ima: 47/47 listenera dobija fajl:linija).

Izvor: 09-ko-menja-polje-i-podrazumevani-konstruktor.md