JPDA 분석 및 원격 디버깅 방법
JPDA 기반 SAS 디버깅 방법
디버깅 모드 사용 불가
(기존) IntelliJ 같은 IDE에서 제공해주는 디버깅 기능을 많이 사용
현재 문제점
배포된 Application을 대상으로, 원하는 지점에서 디버깅을 할 수 있다면 개발 생산성 개선 가능
1. 로컬 디버깅 불가능한 이유 분석
(2) SAS 환경 분석
- SAS(SuperAppServer)
- Java 기반 Client-Server 개발 프레임워크이자 런타임 구동 가능한 플랫폼
- Java Application 개발, 배포, 운영 환경 제공
- SAS의 표준 스펙트로 SAP을 사용
- SAP(SuperAppProtocal)
- 서비스 호출에 사용되는 통신 프로토콜로 TCP/IP 레이어에서 서비스 요청 주고받기 위해 설계됨
- SAS 시스템내에서 처리 최적화를 위해 byte 연산 기반으로 설계된 프로토콜
- 다른 프로토콜을 파싱하는 것보다 특정 byte를 읽어서 데이터 복원이 빠르다 판단하여 설계됨
- SAS에서는 표준 스펙으로 SAP 사용
- SAP로 인코딩된 바이너리 웹 소켓 프레임만을 처리하기 때문에 웹소켓 사용해야 함
- 개발 방법
- SAP 요청 → 비즈니스 로직의 집합을 ServiceObject에 전달
- BodyObject에 요청과 응답을 담아 전달
- BodyObject는 Json과 1:1로 변환 가능한 Datat Object에 해당됨
- SAS는 SAP 내부 바디 프레임을 변환하여 Body Object를 구성함

- 배포 및 서비스 호출 방법
- Standalone 모드
- Standalone 모드에서는 java -jar super-app-runtime.jar와 함께 바로 SAS가 기동됨
- 실행 이후에는 동적 어플리케이션 배포를 지원하지 않음
- 즉, 실행할 어플리케이션 바이너리를
application 디렉토리에 위치시킨 후 SAS를 기동해야 함
- Master-Worker 모드
- sasctl(관리자 도구)을 통해 어플리케이션 제어 가능
- 모든 어플리케이션은 핫 디플로이 형태로 배포되며, 동적으로 패치되거나 삭제 가능
- 어플리케이션 기동을 위해 Master에 어플리케이션 바이너리를 업로드 하고, 어플리케이션 바이너리를 배포하면 됨
- Standalone 모드
(2) SAS를 Standalone 모드로 사용하는 상황
- Standalone 모드
java -jar super-app-runtime.jar명령을 통해 SAS가 독립적으로 실행됨super-app-runtime.jar파일 안에 있는 Java 애플리케이션을 실행하라는 명령어- Standalone 모드에서 이 명령 실행시 SAS 프레임워크가 포함된 Application이 독립적 실행됨
- 이 모드에서는 동적 애플리케이션 배포를 지원하지 않으며, SAS가 실행된 이후에는 애플리케이션을 수정하거나 변경할 수 없음
- 애플리케이션 바이너리를 미리 지정된 디렉토리에 위치시키고, SAS를 기동하는 구조
- IntelliJ IDEA의 로컬 디버깅
- 일반적으로 IntelliJ에서 디버깅 모드 실행하면, IDE 내부에서 JVM을 실행시키고 디버깅 가능함
- Standalone 모드에서는 SAS가 IntelliJ와 독립적으로 실행되기 때문에, IDE가 해당 JVM을 제어하거나 연결할 수 없음 ( 로컬 디버깅 불가능 )
- 원격 디버깅의 필요성
- SAS가 외부에서 JVM을 실행하고 있기 때문에, 로컬 JVM에 연결할 수 없음
- 대신 원격 디버깅을 통해 실행 중인 JVM에 연결하여 디버깅을 수행해야 함
More ⬆︎ `java -jar super-app-runtime.jar` 명령어
- Java 애플리케이션을 실행하기 위한 명령
java: Java 실행 프로그램으로, JVM(Java Virtual Machine)을 시작함jar- 이 옵션은 실행할 파일이 JAR(Java ARchive) 파일임을 나타냄
- JAR 파일은 여러 개의 Java 클래스 파일과 그 관련 리소스를 하나의 파일로 묶은 압축 파일
super-app-runtime.jar- 실제 실행할 JAR 파일의 이름입니다
- 이 파일에는 Java 애플리케이션 코드와 필요한 리소스가 포함되어 있음
More ⬆︎ 애플리케이션 바이너리 파일
- 애플리케이션 바이너리란?
- 컴퓨터가 실행할 수 있는 형태로 변환된 프로그램 파일을 의미함 ( 실행 파일 )
- 소스 코드를 컴퓨터가 이해할 수 있는 언어로 변환한 것이 바이너리 파일
- Java 애플리케이션의 경우
- 소스 코드를 컴파일하면
바이트 코드라는 중간 형태로 변환됨 .class 파일(바이트 코드)을 하나의 압축 파일로 묶은 것이JAR 파일(Java ARchive)- Jar 파일은 자바 애플리케이션을 배포하고 실행하는 데 사용되는 바이너리 파일의 한 형태
- 소스 코드를 컴파일하면
- 바이트 코드가 모여 JAR 파일이 되고, JAR 파일이 실행 가능한 애플리케이션 바이너리에 해당
super-app-runtime.jar와 같은 파일이 애플리케이션 바이너리에 해당됨- Java에서는 이러한 바이너리를 JVM(Java Virtual Machine)이 실행함
즉, 애플리케이션 바이너리는 실행 가능한 프로그램을 담고 있는 파일로, 컴퓨터에서 직접 실행되거나 특정 환경(JVM)에서 실행될 수 있음
More ⬆︎ 가상 운영체제 역할 JVM 구조
-
.java 확장자 소스 파일: 고급 언어에 해당하는 java로 작성된 소스 코드 -
.class 확장자 클래스 파일: 소스 코드를 컴파일러(javac.exe)로 컴파일해 생성된 바이트 코드 파일- 컴파일러는 바이트 코드로 변환하는 역할
- 고급 언어로 작성된 소스 코드는 컴퓨터가 이해할 수 없기 때문에 컴파일 과정을 통해 컴퓨터가 이해할 수 있는 0과 1로 이루어진 기계어로 변환 필요
-
JVM 구동: JVM이 바이트 코드를 운영체제에 맞는 기계어로 변환해 자바 프로그램을 실행-
운영체제가 java 프로그램을 바로 실행 불가 (중간 단계의 바이트코드이기 때문)
-
이 바이트 코드를 해석하고 실행할 수 있는 가상의 운영체제가 필요함
-
JVM 구동 명령(java.exe)에 의해 JVM에서 바이트 코드가 해당 운영체제에 맞게 기계어로 변경됨

-
-
JVM 장단점
- JVM = Java Virtual Machine = 자바를 실행시키는 가상의 기계
- 장점 : 운영체제별 자바 프로그램을 따로 개발할 필요 없음
- 운영체제별로 프로그램 실행 및 관리 방법이 다름
- 운영체제와 자바 프로그램을 중계하는 JVM을 두어 여러 운영체제에서 동일한 실행결과 보장
- 개발자는 운영체제와 상관없이 자바 프로그램을 개발 가능
- 바이트 코드는 하나이지만, JVM에 의해 번역되는 기계어는 운영체제에 따라 달라짐
- 단점 : 속도 느림
- 기계어로 한번에 컴파일링 되지 않고, JVM에 의해 기계어로 번역되고 실행됨
- C와 C++보다 속도 느림 (JVM이 바이트 코드를 실행 시점에 번역하기 때문)
2. Java Platform Debugger Architecture (JPDA) 분석
(1) JPDA 란?
- JPDA는 Java를 디버그하는 데 사용되는 인터페이스 및 프로토콜을 의미함
- JVM TI 와 JDI 라는 2개의 인터페이스 와 JDWP 라는 프로토콜로 크게 구성되어 있음
IDEA 도출
Java Application을 디버깅 모드 실행시 Debuggee와 Debugger가 따로 존재함
Debuggee 와 Debugger 사이에 JDWP 프로토콜 을 통해 소켓 통신을 함
즉, 소켓 통신을 할 수 있으면 디버깅 할 수 있음을 의미함
(2) JPDA 상세 구조

- JVM TI (JVM Tools Interface)
- JVM에서 실행되는 application 실행을 제어하고, 상태 파악에 도움을 주는 인터페이스
- JDI(Java Debug Interface)
- Debugger의 프런트엔드를 구현하기 위해 Java에서 제공하는 인터페이스 집합
- JDI로 구축된 디버거는 JPDA를 지원하는 모든 JVM에서 실행되는 애플리케이션을 디버깅 가능함
- Deburggee의 변수에 대한 액세스와 함께 VM 및 해당 상태에 액세스하는 기능을 제공함
- breakpoint, stepping, watchpoint 및 thread 처리도 설정할 수 있
- JDWP(Java Debugging Wire Protocol)
- Debuggee와 (디버깅 중인 프로세스)와 Debugger(이 경우
IntelliJ IDEA) 간에 전송되는 정보 및 요청의 형식의 프로토콜을 정의
- Debuggee와 (디버깅 중인 프로세스)와 Debugger(이 경우
3. Remote Debugging 적용 방법
SAS에서 실행중인 어플리케이션을 Debuggee로, 이를 디버깅 하는 IntelliJ를 Debugger로 사용
(1) Application 실행시 매개변수 설정
- 서버에서 실행되는 Java Application에 다음 매개변수를 추가해 디버깅을 설정함
// build 후 jar 파일 위치
cd ./build/libs
// 프로젝트 jar 실행 명령어
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10000 -jar application.jar
- 옵션 설명
agentlib:jdwp=transport=dt_socket- JVM이 소켓 방식으로 Debugger와 연결될 수 있도록 설정
- JDWP를 JVM 에이전트로 등록하여, Debugger가 JVM에 소켓 방식으로 연결할 수 있도록 설정
suspend=n: Debugger를 기다리지 않고, 즉시 프로그램을 실행함address = *:(원하는 포트)- Debugger가 원하는 포트에 연결될 수 있도록 설정하면, Debugee가 해당 포트를 Listening 함
- ex. Debugger를 10000번 포트에 연결했으며, Debugee가 10000번 포트를 리스닝 하고 있음
(2) Debugger 연결
Debugee로 실행된 Server에Debugger를 연결Intellij에서 다음과 같은 실행 환경을 추가Run>Edit Configurations에서 Attach to remote JVM 선택- 배포된 서버의 endpoint를 추가하고, 서버를 실행할 때 지정한 Listening 포트를 설정함
- 하나의 BreakPoint 지정하고 디버깅 실행하면, 해당 서버에서 발생한 요청에 대한 디버깅이 가능해짐

(3) Alias 등록 방법
-
debug 별칭으로 쉽게 디버깅 모드 실행 명령어 사용 방법
vi ~/.zshrc -
원하는 alias 등록 하기
alias run = "java -jar super-app-runtime.jar" alias debug="java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=10000 -jar super-app-runtime.jar" -
소스 적용
source ~/.zshrc
(4) 원격 디버깅 주의사항
- 디버깅 모드 사용시 해당 프로세스를 붙잡고 있으므로 불필요한 병목 현상이 발생할 수 있음
- 인증 Key 없이 Debugee의 url과 개방된 포트만 알고 있다면 실행중인 어플리케이션에 쉽게 접근 및 조작 할 수 있기 때문에 보안적 이슈가 존재함