Il existe une autre option qui ne nécessite pas la suppression des flux et qui ne repose pas sur des API non documentées ou non prises en charge. En utilisant un agent Java, il est possible de redéfinir les modules pour exporter/ouvrir les paquets requis. Le code pour cela ressemblerait à quelque chose comme ceci :
void exportAndOpen(Instrumentation instrumentation) {
Set<Module> unnamed =
Collections.singleton(ClassLoader.getSystemClassLoader().getUnnamedModule());
ModuleLayer.boot().modules().forEach(module -> instrumentation.redefineModule(
module,
unnamed,
module.getPackages().stream().collect(Collectors.toMap(
Function.identity(),
pkg -> unnamed
)),
module.getPackages().stream().collect(Collectors.toMap(
Function.identity(),
pkg -> unnamed
)),
Collections.emptySet(),
Collections.emptyMap()
));
}
Vous pouvez maintenant exécuter n'importe quel accès illégal sans l'avertissement puisque votre application est contenue dans le module sans nom comme par exemple :
Method method = ClassLoader.class.getDeclaredMethod("defineClass",
byte[].class, int.class, int.class);
method.setAccessible(true);
Afin de mettre la main sur le Instrumentation
vous pouvez soit écrire un Agent Java ce qui est assez simple et de le spécifier en ligne de commande (plutôt que dans le classpath) en utilisant -javaagent:myjar.jar
. L'agent ne contiendrait qu'un premain
comme suit :
public class MyAgent {
public static void main(String arg, Instrumentation inst) {
exportAndOpen(inst);
}
}
Alternativement, vous pouvez attacher dynamiquement en utilisant l'API attach qui est rendue accessible de manière pratique par le site byte-buddy-agent projet (dont je suis l'auteur) :
exportAndOpen(ByteBuddyAgent.install());
que vous devrez appeler avant l'accès illégal. Notez que cette fonction n'est disponible que sur les JDK et sur les VM Linux, tandis que vous devrez fournir l'agent Byte Buddy sur la ligne de commande en tant qu'agent Java si vous en avez besoin sur d'autres VM. Cela peut être pratique lorsque vous voulez l'auto-attachement sur les machines de test et de développement où les JDK sont généralement installés.
Comme d'autres l'ont souligné, cela ne devrait servir que de solution intermédiaire, mais je comprends parfaitement que le comportement actuel casse souvent les robots d'exploration et les applications de console. C'est pourquoi je l'ai moi-même utilisé dans des environnements de production comme solution à court terme pour utiliser Java 9 et je n'ai rencontré aucun problème jusqu'à présent.
Ce qui est bien, cependant, c'est que cette solution est robuste face aux futures mises à jour car toute opération, même l'attachement dynamique, est légale. En utilisant un processus auxiliaire, Byte Buddy contourne même l'auto-attachement normalement interdit.
0 votes
Je connais cette façon de faire et le problème est déjà signalé. Cependant, j'aimerais désactiver cet avertissement dès maintenant. La correction de ce problème prendra un certain temps.
1 votes
Une fois de plus, je sais que je peux utiliser les drapeaux de la JVM, mais je dois le faire par code. N'ai-je pas été clair ?
3 votes
El
HotSpotDiagnosticMXBean
permet de modifier certaines options de la JVM. Je ne suis pas sûr que vous puissiez l'utiliser pour cette opération, et si vous le pouviez, il est un peu difficile de le faire en production.1 votes
@nullpointer Non. Mon objectif est d'éviter les instructions supplémentaires pour les utilisateurs finaux. Nous avons de nombreux utilisateurs avec nos serveurs installés et cela serait un gros inconvénient pour eux.