J'ai une méthode qui crée des objets lourds comme cache . Ces objets sont rarement consultés, mais coûteux et lents à traiter, et ne sont initialisés que à la demande . Ensuite, lors de l'utilisation de mon application, par exemple, je pourrais demander environ trois objets lourds comme ça, et les réutiliser, mais il est également possible que je l'exécute une fois et qu'il n'occupe que de la mémoire alors que je ne l'utilise plus pendant une session.

Ma question est: est-ce que je peux définir qu'un objet est " garbage collectable ", alors dans le cas où l'application nécessite plus de mémoire, elle désactive ces données inutilisées?

Je pense que cela devrait fonctionner quelque chose comme ça (pseudo-code):

private static MyInstance instance = null;

public static getInstance() {
    if (instance == null) {
        instance = calculate();
        GC.put(instance);
    }

    return instance;
}

Je pense que je peux le faire avec une sorte de minuterie, puis vérifier de temps en temps, mais je suppose que Java devrait avoir quelque chose comme ça, à appeler uniquement si la mémoire est très utilisée.

1
David Rodrigues 21 avril 2017 à 07:28

3 réponses

Meilleure réponse

Oui, Java propose trois types de références qui sont sensibles à l'utilisation de la mémoire.

Un cache peut utiliser un SoftReference qui sera effacé avant que le processus lève un OutOfMemoryError. Tant qu'il y a beaucoup de mémoire, cependant, le SoftReference empêchera son référent d'être ramassé.

1
erickson 21 avril 2017 à 23:50

Java n'a pas de moyen de désallouer manuellement de la mémoire (voir Gestion de la mémoire en Java. Cependant , il dispose d'un ramasse-miettes automatique . Cela signifie que tout objet qui n'a plus de références dans le programme sera automatiquement supprimé. Dans votre cas, par exemple, si un Instance n'est plus utilisé (la fonction qui l'a utilisé renvoie, et aucune autre référence n'existe, ou vous écrasez la seule variable qui a stocké une référence au Instance avec autre chose), que Instance sera récupéré.

Cependant, il n'y a pas de méthode pour faire disparaître le Instance plus rapidement que de se débarrasser de ses références et de laisser le ramasse-miettes s'en occuper.

Ce que je suggérerais plutôt, pour votre application, est quelque chose comme un cache LRU (voir Comment implémenteriez-vous un cache LRU en Java?), ce qui limiterait votre utilisation de la mémoire à un nombre défini d'instances, qui (en fonction de quoi exactement {{X0} } is) vous limiterait à une quantité définie de mémoire utilisée par Instance s.

Si vous vouliez à la place autoriser l'utilisation de toute quantité de mémoire, mais pas utilisée pendant très longtemps , vous pouvez créer une classe wrapper pour Instance, qui implémente votre idée de cache (crée uniquement un Instance lorsqu'il est appelé, si sa copie actuelle est null), mais garde une minuterie et règle son Instance sur null après un laps de temps donné sans qu'il soit utilisé .

1
Community 23 mai 2017 à 12:17

Ce dont vous avez besoin est une mise en œuvre correcte du cache. Il y en a des tonnes en Java, par exemple, Guava Cache, qui est hautement configurable.

Votre méthode calculate est simplement CacheLoader # load.

Vous n'avez pas besoin de vous soucier du GC. Il suffit de dimensionner correctement votre cache pour ne pas utiliser trop de mémoire. Les entrées de cache expulsées sont collectées automatiquement (lorsqu'elles ne sont pas référencées ailleurs).

Je pense que je peux le faire avec une sorte de minuterie, puis vérifier de temps en temps, mais je suppose que Java devrait avoir quelque chose comme ça, à appeler uniquement si la mémoire est très utilisée.

Vous pouvez utiliser l'expulsion basée sur le temps avec par exemple CacheBuilder#expireAfterWrite. Il n'y a pas de mise en cache dans Java lui-même, mais il y a SoftReference. Quoi qu'il en soit, je ne recommande pas de l'utiliser directement, mais envisagez de l'utiliser avec CacheBuilder#softKeys.

1
maaartinus 21 avril 2017 à 23:41