2012-06-07 6 views
0

Je prévois d'utiliser un DirectByteBuffers pour interfacer une bibliothèque tierce écrite en C++.Répliquer DirectByteBuffers OutOfMemoryError

Je me suis inquiété de the hadoop docs en disant:

DirectByteBuffers sont des ordures collectées à l'aide d'une référence fantôme et une file d'attente de référence. De temps en temps, la JVM vérifie la file d'attente de référence et nettoie le DirectByteBuffers. Cependant, comme cela ne se produit pas immédiatement après avoir ignoré toutes les références à un DirectByteBuffer, il est facile de OutOfMemoryError d'utiliser DirectByteBuffers.

D'abord, je ne suis pas sûr que toutes les implémentations de DirectByteBuffers sont les mêmes depuis le OpenJDK 7 ne semble pas utiliser la référence fantôme, mais repose sur la méthode finale qui devrait avoir des pénalités de performance.

En second lieu, j'ai essayé de reproduire un OutOfMemoryError utilisant

public static void main(String[] args) { 
    for(;;){ 
     ByteBuffer buff = ByteBuffer.allocateDirect(1000*1000); 
    } 
} 

et il semble que tout se correctement les déchets collectés. Si tel est le cas sur ma machine en utilisant

java version "1.6.0_31" 
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635) 
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode) 

puis-je compter que cela fonctionnera sur toutes les autres versions de la machine et java> = 1.6?

Merci

+0

La documentation Hadoop est incorrecte: ils ont le processus de retour à l'avant. L'état d'accessibilité de l'élément est d'abord modifié, puis ajouté à la file d'attente de référence. La JVM ne vérifie pas du tout la file d'attente de référence: c'est le code Java. En fait, je ne trouve aucune file d'attente de référence dans le code source: peut-être parle-t-il de sa propre utilisation de DirectByteBuffers? – EJP

Répondre

2

Ce fut un bogue dans les premières versions de Java 6. Cependant, une solution simple qui a été inclus dans la machine virtuelle Java a été de jeter un OutOfMemoryError seulement après le déclenchement d'un System.gc(); Vous pouvez maintenant simuler ce problème en désactivant les CG explicites.

Source for java.nio.Bits.reserveMemory(long)


Je n'attends le GC pour nettoyer les fichiers mis en correspondance ou mémoire directe, au lieu que j'utilise une API interne qui est très bien pour les machines virtuelles, par exemple à base OpenJDK Point chaud. Cela améliore les performances en réduisant les GC complets non essentiels.

((DirectBuffer) buffer).cleaner().clean(); 

Si vous avez des tampons tas, cleaner() renverra null.

+1

Je pensais à libérer manuellement la mémoire, mais je devrais alors m'assurer qu'aucune autre référence à ce tampon n'existe. Ensuite, je devrais compter sur des références fantômes. –

2

This est un excellent article sur le sujet. En ce qui concerne votre test, des tests simples comme celui-ci n'exercent pas vraiment la zone à problème. le problème potentiel se pose lorsque le GC est trop loin derrière. Dans un test comme celui-ci, le GC ne fait rien d'autre alors il n'aura probablement pas de problème à suivre.