Java platvormi siluri arhitektuur

**Java platvormi siluri arhitektuur** (inglise keeles Java Platform Debugger Architecture, lühidalt JDPA) on mitmetasandiline siluri arhitektuur, mis aitab arendajatel luua silumisrakendusi, mida saab teisaldatavalt kasutada eri platvormidel ning mitmesuguste virtuaalmasinate ja Java arenduskomplektidega.

## Tasemed
Java platvormi siluri arhitektuur koosneb kolmest tasandist: Java virtuaalmasina tööriista liides, Java silumise ülekande protokoll ja Java siluriliides.

### Java virtuaalmasina tööriista liides
Java virtuaalmasina tööriista liides (Java Virtual Machine Tool Interface, edaspidi **JVM TI**) defineerib silutavad teenused, mida virtuaalmasin pakub. See sisaldab nii infopäringuid, tegevusi (näiteks kuhu asetada katkestuspunkt) ja teateid (näiteks kood jõudis katkestuspunktini).

### Java silumise ülekande protokoll
Java silumise ülekande protokoll (Java Debug Wire Protocol, edaspidi **JDWP**) defineerib siluri ja silutavate protsesside vahelise kommunikatsiooni.

### Java siluriliides
Java siluriliides (Java Debug Interface, edaspidi **JDI**) defineerib kõrgetasemelise Java keele liidese, mida tööriista arendajad saavad kasutada kaugsiluri rakenduste kirjutamiseks.

## Näiterakendus
Oracle on lisaks kolme taseme liideste kirjeldusele välja andnud ka kirjeldust täitva näidisrakenduse, mis koosneb järgnevatest osadest: 

# Java virtuaalmasina tööriista liidese rakendus mitmele virtuaalmasinale. 
# Taustaprogramm, mis kasutab liidest JVM TI, et implementeerida silutav osa protokollist JDWP.
# Kasutajaliides, mis kasutab siluri poolel protokolli JDWP, et implementeerida liides JDI.
# Kaks lihtsat näidet silumisrakendusest, mis on kirjutatud liidesega JDI.

## Siluri arhitektuuri kasutamine
Siluri arendaja võib siluri arhitektuuri kasutada ükskõik mis tasemel. Kuna JDI on kõige kõrgemal tasemel ja kõige lihtsam kasutada, siis kasutatakse seda enim siluri loomiseks. Selle peamiseks eeliseks on teisaldatavus - seda saab kasutada eri platvormide ja virtuaalmasinate peal ilma koodi muutmata.

Kui arendajal on vaja rohkem funktsionaalsust, siis on võimalik ka kirjutada rakendus, mis on ehitatud protokolli JDWP või liidese JVM TI peale. Näiteks siluriliidese arendamine mõnele teisele keelele on võimalik ainult JDWP või JVM TI abil.

Kõige levinumat kasutust siluri arhitektuurile pakuvad integreeritud arenduskeskkonnad, kus on tihti juba olemas graafiline ja lihtsasti arusaadav kasutajaliides programmi silumiseks. Sellisteks keskkondadeks on näiteks Eclipse, IntelliJ IDEA, NetBeans ja JDeveloper.

## Näide JDI kasutamisest
Allolev Java programm loob liidest JDI kasutades ühenduse virtuaalmasinaga samal arvutil pordil 5005. Seejärel saadab programm virtuaalmasinale üle JDWP käsu lisada klassi 'näide.SilutavKlass' reale 10 katkestuspunkti ning pärast seda küsib virtuaalmasinalt kas katkestuspunkti on läbitud.


```java
public static void main(String[] args) throws Exception {
  // Leia JDI siluri ühendaja
  Connector ühendaja = Bootstrap.virtualMachineManager().allConnectors().stream()
      .filter(c -> c.name().equals("com.sun.jdi.SocketAttach"))
      .findFirst().get();

  // Määra silutava virtuaalmasina aadressiks localhost:5005
  Map<String, Connector.Argument> argumendid = ühendaja.defaultArguments();
  argumendid.get("hostname").setValue("localhost");
  argumendid.get("port").setValue("5005");

  // Ühenda virtuaalmasinaga
  VirtualMachine silutavVirtuaalMasin = ((AttachingConnector) ühendaja).attach(argumendid);

  // Küsi silutavalt virtuaalmasinalt viidet klassile 'näide.SilutavKlass'
  ReferenceType klassiViide = silutavVirtuaalMasin.classesByName("näide.SilutavKlass").get(0);

  // Leia katkestuspunkti asukoht real 10 klassis 'näide.SilutavKlass'
  Location katkestuspunktiAsukoht = klassiViide.allLineLocations().stream()
      .filter(loc -> loc.lineNumber() == 10)
      .findFirst().get();

  // Lisa katkestuspunkt
  BreakpointRequest breakPointRequest = silutavVirtuaalMasin.eventRequestManager().createBreakpointRequest(katkestuspunktiAsukoht);
  breakPointRequest.enable();

  // Prindi välja katkestuspunktis peatumised
  while (!Thread.interrupted()) {
    EventSet teated = silutavVirtuaalMasin.eventQueue().remove();
    
    teated.stream()
        .filter(event -> Objects.equals(event.request(), breakPointRequest))
        .forEach(teade -> System.out.println("Virtuaalmasin peatus katkestuspunktis " + ((BreakpointRequest) teade).location()));

    // Juhul kui leiti mõni teade, siis pärast selle käsitlemist palume virtuaalmasinal oma tööd jätkata
    if (!teated.isEmpty()) {
      silutavVirtuaalMasin.resume();
    }
  }
}
```


## Viited

## Välislingid
* JVM TI spetsifikatsioon
* JDWP spetsifikatsioon
* JDWP transpordi spetsifikatsioon
* JDI spetsifikatsioon