Compatibilidad y alcance de la protección

P4JX cifra las implementaciones de los métodos de las clases protegidas y solo deja que las lea, en tiempo de ejecución, el VLX JRE incluido en el paquete. Para que la protección sea sólida sin romper los frameworks, proteja únicamente la lógica de negocio principal y deje fuera los puntos de entrada del framework, los DTO y las entidades, las clases que el framework genera o modifica en tiempo de ejecución y las dependencias de terceros.

1. Ejecute primero un escaneo de compatibilidad

Solo escanear, sin generar nada:

p4j javaapp app.jar --compat-scan
p4j springboot app.jar --compat-scan
p4j tomcat app.war --compat-scan

Escanear y aplicar las recomendaciones conservadoras:

p4j springboot app.jar dist --compat-apply

Las opciones que indique de forma explícita tienen siempre prioridad sobre las recomendaciones automáticas. El escaneo es un análisis heurístico estático: una entrada de «revisión necesaria» no significa que la aplicación vaya a fallar, y un informe limpio no sustituye a las pruebas de regresión en la plataforma de destino.

Cuando el escaneo pide cambiar el código

Si el informe muestra ACTION REQUIRED, hay que modificar el código fuente de la aplicación: ninguna combinación de opciones de empaquetado lo resuelve. El informe indica las clases y los métodos concretos y propone una de estas soluciones:

  • Lectura de un ZIP o un JAR desde memoria: sustituya ByteArrayInputStream por un método basado en archivos, como Files.newInputStream(Path), FileInputStream, ZipFile o JarFile.
  • Definición de clases a partir de bytes: no llame a ClassLoader#defineClass sobre una clase protegida. Use Class.forName() o ClassLoader.loadClass() y deje que el entorno de ejecución P4JX la cargue.

Tras cambiar el código, vuelva a compilar el JAR o el WAR y repita el escaneo. Genere el paquete protegido solo cuando el informe ya no señale el problema.

2. Modelo de protección recomendado

frontera pública / entrada del framework → fachada o interfaz corriente → implementación principal protegida

Por ejemplo:

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

3. Clases que normalmente conviene dejar sin proteger

  • controladores, servlets, filtros, escuchadores y clases de tipo advice;
  • clases de configuración de Spring y objetos ampliados con AOT o CGLIB;
  • DTO de Jackson, records, entidades JPA y modelos de serialización;
  • clases puente de JNI, SWT y otras interfaces nativas;
  • clases que un agente, un ORM, una biblioteca de simulación, una herramienta de recarga en caliente o un ClassLoader propio reescriben o redefinen;
  • frameworks de terceros y dependencias de código abierto;
  • clases que necesitan leer su propio bytecode real.

4. Funciones de la JVM no admitidas o limitadas

Entorno de ejecución

  • La aplicación protegida debe ejecutarse con el VLX JRE que la acompaña.
  • No se admite el arranque mediante la forma -m de JPMS ni desde un único archivo fuente.
  • Los JAR corrientes del classpath deben estar registrados por el empaquetador y no pueden añadirse libremente al desplegar.
  • No use el VLX JRE para ejecutar aplicaciones sin proteger.

Depuración y agentes

  • No se admiten JVMTI, los depuradores JDWP, los perfiladores, las herramientas de cobertura ni la mayoría de los agentes APM.
  • No se admiten -javaagent, -agentlib, la recarga en caliente ni la redefinición de clases.
  • Cualquier tejido de bytecode debe completarse antes de la codificación.

Optimización del arranque

  • No se admiten CDS, AppCDS ni AOT.
  • ZGC y Shenandoah GC quedan fuera del alcance del entorno de ejecución P4JX.

5. Recursos de clase y escáneres

Al leer el recurso .class de una clase protegida se obtiene un esbozo de metadatos: se conservan el nombre de la clase, las firmas y las anotaciones, pero no los cuerpos reales de los métodos.

  • La reflexión corriente puede leer los metadatos, pero no recuperar el bytecode original.
  • Las herramientas que analizan el ZIP físico por su cuenta no ven nada dentro de un archivo P4JX; pruebe con --zip-overlay scanner.
  • Los escáneres de classpath como ClassGraph y Reflections pueden necesitar --layout fat con Spring Boot.
  • No se admite analizar un archivo P4JX desde un flujo en memoria o de red con ZipInputStream o JarInputStream.
  • La vista zipfs es de solo lectura, así que no permite modificar el archivo.

6. Comportamiento del archivo

  • El sufijo .jar no lo convierte en un JAR corriente: el contenido sigue siendo P4JX.
  • Los JAR multiversión se aplanan a la versión de Java de destino durante la codificación.
  • No se conservan las firmas ni la semántica de certificados del JAR original; firme el resultado final por separado si su distribución lo exige.
  • No modifique, recomprima ni combine los archivos P4JX generados.