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).
Özet
1. Uygulamayı şu seçenekler ile başlatmak gerekir
agentlib
transport
server
address
"-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
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
java -jar target/CLI-0.0.6-SNAPSHOT-shaded.jar -pid=62604
Örnek - socket portu
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
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ızapiVersion: 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
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.