호환성과 보호 범위
P4JX는 보호 대상 클래스의 메서드 구현을 암호화해 저장하고, 실행 시에는 패키지에 포함된 VLX JRE만 이를 읽을 수 있게 합니다. 보호 강도와 프레임워크 호환성을 함께 확보하려면 핵심 업무 로직만 보호하고, 프레임워크 진입점, DTO와 엔티티, 프레임워크가 실행 중에 생성하거나 수정하는 클래스, 서드파티 의존성은 보호 범위에서 제외하는 것이 좋습니다.
1. 먼저 호환성 검사를 실행하세요
검사만 하고 결과물은 만들지 않는 경우:
p4j javaapp app.jar --compat-scan
p4j springboot app.jar --compat-scan
p4j tomcat app.war --compat-scan
검사한 뒤 보수적인 권장 설정을 적용하는 경우:
p4j springboot app.jar dist --compat-apply
직접 지정한 옵션은 언제나 자동 권장보다 우선합니다. 검사는 정적 휴리스틱 분석입니다. 「확인 필요」로 보고되어도 반드시 문제가 생기는 것은 아니며, 문제가 없다고 보고되어도 대상 플랫폼에서의 회귀 테스트를 대신할 수는 없습니다.
검사 결과가 코드 수정을 요구하는 경우
GUI 보고서에 ACTION REQUIRED가 표시되면 애플리케이션 소스 코드를 수정해야 합니다. 패키징 옵션을 어떻게 바꿔도 해결되지 않습니다. 보고서에는 해당 클래스와 메서드가 표시되고, 다음 중 하나의 조치가 제시됩니다.
- ZIP이나 JAR를 메모리에서 읽는 경우:
ByteArrayInputStream대신Files.newInputStream(Path),FileInputStream,ZipFile,JarFile같은 파일 기반 방식으로 바꿉니다. - 원시 바이트에서 클래스를 정의하는 경우: 보호 대상 클래스에
ClassLoader#defineClass를 직접 호출하지 말고,Class.forName()또는ClassLoader.loadClass()를 사용해 클래스 로딩을 P4JX 런타임에 맡깁니다.
소스를 수정했다면 JAR 또는 WAR를 다시 빌드하고 호환성 검사를 한 번 더 실행하세요. 보고서에서 해당 문제가 사라진 뒤에 보호 패키지를 만드세요.
2. 권장하는 보호 모델
공개 경계·프레임워크 진입점 → 일반 파사드 또는 인터페이스 → 보호된 핵심 구현
예:
--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'
3. 보통 보호하지 말아야 할 클래스
- 컨트롤러, 서블릿, 필터, 리스너, 어드바이스
- Spring 설정 클래스와 AOT·CGLIB로 확장된 객체
- Jackson DTO, 레코드, JPA 엔티티, 직렬화 모델
- JNI, SWT 등 네이티브 브리지 클래스
- 에이전트, ORM, 목(mock), 핫 리로드, 사용자 정의 ClassLoader가 다시 쓰거나 재정의하는 클래스
- 서드파티 프레임워크와 오픈소스 의존성
- 자기 자신의 실제 바이트코드를 읽어야 하는 클래스
4. 지원하지 않거나 제한되는 JVM 기능
실행 환경
- 보호된 애플리케이션은 함께 제공되는 VLX JRE로 실행해야 합니다.
- JPMS의
-m방식 실행과 단일 소스 파일 실행은 지원하지 않습니다. - 클래스패스에 있는 일반 JAR는 패키저에 등록되어 있어야 하며, 배포 시점에 임의로 추가할 수 없습니다.
- 보호되지 않은 일반 애플리케이션을 VLX JRE로 실행하지 마세요.
디버깅과 에이전트
- JVMTI, JDWP 디버거, 프로파일러, 커버리지 도구, 대부분의 APM 에이전트는 지원하지 않습니다.
-javaagent,-agentlib, 핫 리로드, 클래스 재정의는 지원하지 않습니다.- 바이트코드 위빙은 인코딩 전에 끝나 있어야 합니다.
시작 최적화
- CDS, AppCDS, AOT는 지원하지 않습니다.
- ZGC와 Shenandoah GC는 P4JX 런타임의 지원 범위 밖입니다.
5. 클래스 리소스와 스캐너
보호 대상 클래스의 .class 리소스를 읽으면 메타데이터 스텁을 얻습니다. 클래스 이름, 시그니처, 애너테이션은 유지되지만 실제 메서드 본문은 들어 있지 않습니다.
- 일반적인 리플렉션으로 메타데이터는 읽을 수 있지만 원래 바이트코드는 복원할 수 없습니다.
- 물리적 ZIP을 직접 해석하는 도구는 기본적으로 P4JX 아카이브의 내용을 보지 못합니다.
--zip-overlay scanner를 시도해 보세요. - ClassGraph, Reflections 같은 클래스패스 스캐너는 Spring Boot에서
--layout fat이 필요할 수 있습니다. ZipInputStream이나JarInputStream으로 메모리 스트림이나 네트워크 스트림에서 P4JX를 해석하는 것은 지원하지 않습니다.- zipfs 뷰는 읽기 전용이므로 이를 통해 아카이브를 수정할 수 없습니다.
6. 아카이브 동작
.jar확장자라도 일반 JAR가 아니며 내용은 여전히 P4JX입니다.- 멀티 릴리스 JAR는 인코딩할 때 대상 Java 버전으로 평탄화됩니다.
- 원래 JAR의 서명과 인증서 의미는 유지되지 않습니다. 배포에 필요하다면 최종 산출물에 별도로 서명하세요.
- 생성된 P4JX 파일을 수정하거나 다시 압축하거나 병합하지 마세요.