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
ByteArrayInputStreampor uma abordagem baseada em arquivos, comoFiles.newInputStream(Path),FileInputStream,ZipFileouJarFile. - Definição de classe a partir de bytes brutos: não chame
ClassLoader#defineClassnuma classe protegida. UseClass.forName()ouClassLoader.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
-mdo 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 fatcom o Spring Boot. - Analisar um arquivo P4JX a partir de um fluxo em memória ou de rede com
ZipInputStreamouJarInputStreamnão tem suporte. - A visão zipfs é somente leitura, portanto não permite alterar o arquivo.
6. Comportamento do arquivo
- Um sufixo
.jarnã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.