Compatibilidade e alcance da proteção

O P4JX criptografa as implementações dos métodos das classes protegidas e só permite que o VLX JRE incluído no pacote as leia em tempo de execução. Para conciliar uma boa proteção com a compatibilidade dos frameworks, proteja apenas o núcleo da lógica de negócio e deixe de fora os pontos de entrada do framework, os DTOs e as entidades, as classes que o framework gera ou modifica em tempo de execução e as dependências de terceiros.

1. Faça primeiro uma verificação de compatibilidade

Apenas verificar, sem gerar nada:

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

Verificar e aplicar as recomendações conservadoras:

p4j springboot app.jar dist --compat-apply

As opções que você informa explicitamente sempre prevalecem sobre as recomendações automáticas. A verificação é uma análise heurística estática: uma marcação de «revisão necessária» não significa que o aplicativo vá falhar, e um relatório sem apontamentos não substitui os testes de regressão na plataforma-alvo.

Quando a verificação exige mudar o código

Se o relatório mostrar ACTION REQUIRED, é preciso alterar o código-fonte do aplicativo: nenhuma combinação de opções de empacotamento resolve. O relatório indica as classes e os métodos envolvidos e propõe uma destas correções:

  • Leitura de um ZIP ou JAR a partir da memória: troque ByteArrayInputStream por uma abordagem baseada em arquivos, como Files.newInputStream(Path), FileInputStream, ZipFile ou JarFile.
  • Definição de classe a partir de bytes brutos: não chame ClassLoader#defineClass numa classe protegida. Use Class.forName() ou ClassLoader.loadClass() e deixe o tempo de execução do P4JX carregá-la.

Depois de alterar o código, reconstrua o JAR ou o WAR e refaça a verificação. Só gere o pacote protegido quando o relatório não apontar mais o problema.

2. Modelo de proteção recomendado

fronteira pública / entrada do framework → fachada ou interface comum → implementação central protegida

Por exemplo:

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

3. Classes que normalmente devem ficar sem proteção

  • controladores, servlets, filtros, ouvintes e classes de advice;
  • classes de configuração do Spring e objetos ampliados por AOT ou CGLIB;
  • DTOs do Jackson, records, entidades JPA e modelos de serialização;
  • classes-ponte JNI, SWT e outras interfaces nativas;
  • classes que um agente, um ORM, uma biblioteca de simulação, uma ferramenta de recarga a quente ou um ClassLoader próprio reescreve ou redefine;
  • frameworks de terceiros e dependências de código aberto;
  • classes que precisam ler o próprio bytecode real.

4. Recursos da JVM sem suporte ou limitados

Ambiente de execução

  • Um aplicativo protegido deve ser executado com o VLX JRE que o acompanha.
  • A inicialização pela forma -m do JPMS e a partir de um único arquivo-fonte não têm suporte.
  • Os JAR comuns do classpath precisam estar registrados pelo empacotador e não podem ser acrescentados livremente na implantação.
  • Não use o VLX JRE para executar aplicativos sem proteção.

Depuração e agentes

  • JVMTI, depuradores JDWP, perfiladores, ferramentas de cobertura e a maioria dos agentes de APM não têm suporte.
  • -javaagent, -agentlib, a recarga a quente e a redefinição de classes não têm suporte.
  • Qualquer tecelagem de bytecode precisa estar concluída antes da codificação.

Otimização de inicialização

  • CDS, AppCDS e AOT não têm suporte.
  • ZGC e Shenandoah GC estão fora do alcance do tempo de execução do P4JX.

5. Recursos de classe e scanners

Ler o recurso .class de uma classe protegida devolve um esboço de metadados: o nome da classe, as assinaturas e as anotações são preservados, mas não o corpo real dos métodos.

  • A reflexão comum lê os metadados, mas não recupera o bytecode original.
  • As ferramentas que analisam o ZIP físico por conta própria não enxergam nada dentro de um arquivo P4JX por padrão; experimente --zip-overlay scanner.
  • Scanners de classpath como ClassGraph e Reflections podem precisar de --layout fat com o Spring Boot.
  • Analisar um arquivo P4JX a partir de um fluxo em memória ou de rede com ZipInputStream ou JarInputStream não tem suporte.
  • A visão zipfs é somente leitura, portanto não permite alterar o arquivo.

6. Comportamento do arquivo

  • Um sufixo .jar não o torna um JAR comum: o conteúdo continua sendo P4JX.
  • Os JAR multiversão são achatados para a versão-alvo do Java durante a codificação.
  • As assinaturas e a semântica de certificado do JAR original não são preservadas; assine o entregável final separadamente se a sua distribuição exigir.
  • Não altere, recomprima nem combine os arquivos P4JX gerados.