Un programme que j'ai développé est en train de casser la JVM occasionnellement en raison de ce bogue: http: // bugs.java.com/bugdatabase/view_bug.do?bug_id=8029516 . Malheureusement, le bogue n'a pas été résolu par Oracle et le rapport de bogue indique qu'il n'y a pas de solution de contournement connue. p>
J'ai essayé de modifier le code exemple du rapport de bogue en appelant .EGRISTER (SwatchService, Eventkinds) dans le fil de KeyWatcher à la place, en ajoutant toute la demande de registre en attente à une liste que je boucle dans le fil de clé KeyWatcher, mais c'est toujours écrasé. Je suppose que cela a juste eu le même effet que la synchronisation sur SwatchService (comme l'émetteur du rapport de bogue essayé). P>
Pouvez-vous penser à quelque moyen de se déplacer? P>
3 Réponses :
Vous pourriez ne pas être capable de contourner le problème lui-même, mais vous pouvez faire face à l'erreur et le gérer. Je ne connais pas votre situation spécifique mais je pouvais imaginer que le problème le plus important est le crash de l'ensemble de la JVM. Mettre tout dans un Ne pas en savoir plus sur votre projet, il est difficile de suggérer une solution bonne / acceptable, mais peut-être que cela pourrait être une option: faites tout le fichier en regardant des trucs dans un processus JVM distinct. Depuis votre processus principal, commencez une nouvelle JVM (par exemple, en utilisant Maintenant, la plus grande partie restante est de mettre en œuvre une certaine communication entre le processus principal et le processus de surveillance des fichiers. Cela pourrait être fait en utilisant la norme / sortie de Le processus de surveillance du fichier ou à l'aide d'un Essayez CODE> Block ne fonctionne pas car vous ne pouvez pas attraper un crash JVM. P>
processbuilder.start () code>
). Lorsque le processus se termine (c'est-à-dire les crashs JVM nouvellement démarrés), redémarrez-le. Évidemment, vous devez être capable de récupérer, c'est-à-dire que vous devez suivre les fichiers à regarder et vous devez également conserver ces données dans votre processus principal. P>
socket Code>
/ ServerSocket code>
ou un autre mécanisme. P>
des commentaires:
Il semble que nous ayons un problème avec l'annulation d'E / S lorsqu'il y a une inscription en attente de readdirectorychangew exceptionnel. P> BlockQuote>
La déclaration et l'exemple du code indiquent que le bogue est déclenché lorsque: p>
- Il y a un événement en attente qui n'a pas été consommé (il peut être visible ou non à
watchservice.poll () code> ou
watchservice.take () code>) li>
watchkey.cancel () code> est appelé sur la clé li> ol>
Ceci est un bogue désagréable sans solution de contournement universelle. L'approche dépend des spécificités de votre application. Considérez la mise en commun des montres à une seule place afin que vous n'ayez pas besoin d'appeler
watchkey.cancel () code>. Si, à un moment donné, la piscine devient trop grande, fermez l'ensemble de la surveillance code> et recommencez. Quelque chose de similaire à. P>
xxx pré> p>
J'ai réussi à créer une solution de contournement s'il est un peu moche.
Le bogue est dans la méthode JDK voici Un compilé patch à JDK. Pour appliquer, ajoutez le drapeau de ligne de commande Java suivant: Si Patching JDK n'est pas une option dans votre cas, il reste encore une solution de contournement sur le niveau d'application. Il repose sur la connaissance de la mise en œuvre interne de Windowservice Windows WatchService. P> windowswatchkey.invalidate () code> qui libère un tampon natif pendant que les appels ultérieurs peuvent toujours y accéder. Cet one-liner corrige le problème en retardant le nettoyage tampon jusqu'à ce que gc. p>
-XBootClassPath / P: JDK-8029516-PATCH.JAR CODE> P>
public class JDK_8029516 {
private static final Field bufferField = getField("sun.nio.fs.WindowsWatchService$WindowsWatchKey", "buffer");
private static final Field cleanerField = getField("sun.nio.fs.NativeBuffer", "cleaner");
private static final Cleaner dummyCleaner = Cleaner.create(Thread.class, new Thread());
private static Field getField(String className, String fieldName) {
try {
Field f = Class.forName(className).getDeclaredField(fieldName);
f.setAccessible(true);
return f;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public static void patch(WatchKey key) {
try {
cleanerField.set(bufferField.get(key), dummyCleaner);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
Impressionnant! Cela fonctionnait parfaitement. Je suis très impressionné et reconnaissant!
Joli! @apangin Avez-vous envisagé de poster votre correctif proposé à Mail.openjdk.java. Net / Mailman / Listinfo / Core-Libs-dev Liste de diffusion?
Impair. Ça marche pour moi. J'ai juste vérifié.
Le lien a fonctionné et non travaillé pour moi. Probablement un problème d'oracle. Sans voir de code, il est difficile de répondre, mais réorganiser votre code pour avoir un et un seul B> Watch thread responsable des classes de surveillance et de watchKey. D'autres threads utiliseraient ces classes ou services via votre classe de surveillance.
Ceci est un problème dans la libération de la mémoire de la mémoire native. Je soupçonne que la bibliothèque Windows implémente Malloc / Gratuit qui est à blâmer. Je vérifierais que vous avez la dernière DLL, cela pourrait être.
@GilbertleBlanc J'ai essayé de tout faire dans le fil de l'observateur mais je m'écrase parfois parfois.
@Peterlawrey Qu'est-ce qui vous fait penser que GRATUIT est à blâmer? Il pourrait également être que Java essaie de libérer quelque chose qu'il n'a pas malcupé.
@Yrlec ayant lu le code, c'est assez simple. Plus probablement est qu'il essaie de libérer la mémoire plus d'une fois si quelque chose.