18 Temmuz 2019 Perşembe

Java Debug Wire Protocol - JDWP - Remote Debug İçindir

Giriş
JDWP yani protokol aslında  Java Debugger Platform Architecture (JDPA)'ın bir parçası. Açıklaması şöyle
JDPA, developed by Sun Microsystems, is a multi-tiered architecture that allows users to connect to remote Java applications through their local IDE and perform the necessary debugging on the remote system. As can be seen from the diagram above, the JDPA consists of three main interfaces. These are the Java Virtual Machine Tool Interface (JVM TI), the Java Debug Wire Protocol (JDWP), and the Java Debug Interface (JDI).
Şeklen şöyle

Özet
1. Uygulamayı şu seçenekler ile başlatmak gerekir
agentlib
transport
server
address
Yani şöyle
"-Xdebug -agentlib:jdwp=transport=dt_socket,address=0.0.0.0:5005,server=y,suspend=n"

2. Debugger'ı da aynı bu porta bağlanacak şekilde başlatırız

1. Debugger 

1.1 Java Debug Interface - JDI
Açıklaması şöyle
The JDI can be thought of as simply a Java API that is aimed at capturing requests and relaying information to and from the debugger. This also means that the debugger interface can be writing in any language as long as it calls upon the correct set of API endpoints provided. On the opposite end is the JVM TI which is a native programming interface. It communicates with the services in the VM and can observe and control the execution of the Java applications.
1.2 Debugger İle Bağlanma
Java uygulaması remote debug seçeneği ile başlatıldıysa debugger ile bağlanmak için şöyle yaparız

Örnek - process id
Şöyle yaparız
java -jar target/CLI-0.0.6-SNAPSHOT-shaded.jar -pid=62604
Örnek - socket portu
Şöyle yaparız
java -jar target/CLI-0.0.6-SNAPSHOT-shaded.jar -attach=8000

2. Uygulama İçin Parametreler
Uygulamamamızı uzaktan debug edebilmek için şu parametreler ile çalıştırmak gerekir.
Örnek
Kubernetes ortamında şöyle yaparız
java -agentlib:jdwp=transport=dt_socket,server=y,address=9000 ApplicationName #ssh ile güvenli hale getirme ssh remoteUser@remoteHost -L 9000:127.0.0.1:9000 -N # kubernetes ortamında portu dışarı açma kubectl port-forward podname 9000:9000
Örnek
Kubernetes ortamında deployment için şöyle yaparız
apiVersion: apps/v1
kind: Deployment
metadata:
  name: application-deployment
spec:
  selector:
    matchLabels:
      app: application
  template:
    metadata:
      labels:
         app: application
    spec:
      containers:
        - image: ghcr.io/amrutprabhu/remote-application:1.0.0-SNAPSHOT
          imagePullPolicy: Always
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
            - name: debug-port
              containerPort: 5005
              protocol: TCP
          env:
            - name: JAVA_TOOL_OPTIONS
              value: "-Xdebug -agentlib:jdwp=transport=dt_socket,address=0.0.0.0:5005, server=y,suspend=n"
Daha sonra şöyle yaparız. Böylece debugger 5005'e bağlanınca aslında pod'a bağlanacak
kubectl port-forward <your pod name> 5005:5005

Örnek
Şöyle yaparız
java -Xdebug
  -Xnoagent
  -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
  -jar spring-petclinic-2.5.0-SNAPSHOT.jar
  -Dagentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
address Alanı
Açıklaması şöyle. Eğer server=y ise sadece port numarasını belirtir.
address=8000 specifies the address at which the debug socket will listen. In this case, the JVM will listen at port 8000 for incoming connections only from the local host (starting JDK 9).
Açıklaması şöyle.
To bind the socket to addresses allowing remote connections, either prefix the port with the host name, IP address, or an asterisk (*) to bind to all available IP addresses:
-agentlib:jdwp=transport=dt_socket,server=y,address=host1:8000
or
-agentlib:jdwp=transport=dt_socket,server=y,address=*:8000
Örnek
Şöyle yaparız. Burada 5005 numaralı port dinleniyor. Debugger bu porta bağlanacak.
FROM openjdk:11
VOLUME /tmp
EXPOSE 8082
ADD /target/catalogservice-0.0.1-SNAPSHOT.jar catalogservice-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n", 
  "-jar", "catalogservice-0.0.1-SNAPSHOT.jar"]
agentlib alanı
Şöyle yaparız. Buraya hep jdwp yazılıyor
-agentlib:jdwp=transport=dt_socket,server=y,address=localhost:8000.
transport alanı
dt_socket veya dt_shmem değerlerini alabilir.

server Alanı
Açıklaması şöyle.
server=y means that the JVM will listen for a debugger to attach to it.
Normalde server alanı ile address alanı birlikte kullanılır. Eğer address alanı belirtilmezse JVM kendisi bir adres seçer. Açıklaması şöyle.
If server=y (i.e. JVM is listening for connection), we can skip the address option, which will make it use a dynamically assigned port. Since no address was specified, this allows only local connections. The chosen port will be displayed at stdout of the JVM, e.g.:

Listening for transport dt_socket at address: 12345
suspend Alanı
Açıklaması şöyle.
suspend=y means the JVM will wait for the debugger to attach before executing the main class. This is also the default value. If set to n, the JVM will immediately execute the main class, while listening for the debugger connection.

Hiç yorum yok:

Yorum Gönder