호환성 및 보호 범위

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 읽기:ByteArrayInputStreamFiles.newInputStream(Path), FileInputStream, ZipFile 또는 JarFile와 같은 파일 기반 읽기 방식으로 변경하십시오.
  • 원시 바이트로 클래스 정의:보호된 클래스에 직접 ClassLoader#defineClass를 호출하지 말고, 대신 Class.forName() 또는 ClassLoader.loadClass()를 사용하여 P4JX가 실행될 때 클래스를 로드하도록 하십시오.

소스 코드를 수정한 후 JAR/WAR를 다시 빌드하고 호환성 스캔을 다시 수행하십시오. 보고서에 해당 문제가 더 이상 표시되지 않는 것을 확인한 후에 보호 패키지를 생성하십시오.

2. 권장되는 보호 모델

공개된 경계/프레임워크 입구 → 일반적인 facade 또는 인터페이스 → 보호된 핵심 구현

예시:

--protect 'com.example.service.impl.**' \
--exclude 'com.example.dto.**,com.example.config.**'

3. 일반적으로 보호하지 않아야 하는 클래스

  • Controller, Servlet, Filter, Listener, Advice;
  • Spring Configuration, AOT/CGLIB로 강화된 객체;
  • Jackson DTO, record, JPA Entity, 시리얼라이제이션 모델;
  • JNI/SWT/native 브리지 클래스;
  • Agent, ORM, Mock, 핫 리로딩 또는 사용자 정의 ClassLoader에 의해 수정/재정의된 클래스;
  • 서드파티 프레임워크 및 오픈소스 의존성;
  • 자신의 실제 class 바이트코드를 읽어야 하는 클래스.

4. 지원되지 않거나 제한된 JVM 기능

실행 환경

  • 보호된 애플리케이션은 반드시 패키지에 포함된 VLX JRE를 사용해야 합니다;
  • JPMS -m 방식의 시작 및 단일 파일 소스코드로의 시작은 지원되지 않습니다;
  • classpath에 있는 일반 JAR은 반드시 패키징 도구를 통해 등록되어야 하며, 배포 시 임의로 추가될 수 없습니다;
  • 보호되지 않은 일반 애플리케이션을 VLX JRE를 사용하여 실행해서는 안 됩니다.

디버깅 및 Agent

  • JVMTI, JDWP 디버거, 성능 분석 도구, 커버리지 도구 및 대부분의 APM agent는 지원되지 않습니다;
  • -javaagent, -agentlib, 핫 리로드, 클래스 재정의는 지원되지 않습니다;
  • 바이트코드 인라인 처리가 필요한 경우는 코드를 인코딩하기 전에 먼저 수행되어야 합니다.

시작 최적화

  • CDS, AppCDS, AOT는 지원되지 않습니다;
  • ZGC와 ShenandoahGC는 P4JX 런타임의 지원 범위에 포함되지 않습니다.

5. 클래스 리소스 및 스캐너

보호된 클래스인 .class의 리소스를 읽을 경우 메타데이터만 획득됩니다. 클래스명, 서명, 주석은 그대로 유지되지만 실제 메서드 본문은 포함되지 않습니다.

  • 일반 리플렉션을 사용하면 메타데이터는 읽을 수 있지만 원본 바이트코드를 복원할 수는 없습니다.
  • 물리적 ZIP 파일을 직접 파싱하는 도구는 기본적으로 P4JX의 내용을 볼 수 없으며, --zip-overlay scanner를 사용해 보는 것이 좋습니다.
  • ClassGraph, Reflections와 같은 클래스패스 스캐너는 Spring Boot 환경에서 --layout fat가 필요할 수 있습니다.
  • ZipInputStream/JarInputStream를 사용해 메모리나 네트워크 스트림에서 P4JX를 파싱하는 기능은 지원되지 않습니다.
  • zipfs 뷰는 읽기 전용이므로 아카이브를 수정할 수 없습니다.

6. 아카이빙 동작

  • .jar 접미사는 일반 JAR을 의미하지 않으며, 내용은 여전히 P4JX 형태입니다;
  • Multi-Release JAR은 인코딩 시 대상 Java 버전에 맞게 평면화됩니다;
  • 원본 JAR의 서명 및 인증서 정보는 유지되지 않으므로, 필요한 경우 최종 배포 파일에 별도로 서명을 해야 합니다;
  • 생성된 P4JX 파일을 수정하거나 재압축하거나 병합해서는 안 됩니다.