Les String en Java son immuables (immutable).

In the Java programming language, unlike C, an array of char is not a String,and neither a String nor an array of char is terminated by '\u0000' (the NUL character). A String object is immutable, that is, its contents never change, while an array of char has mutable elements. The method toCharArray in class String returns an array of characters containing the same character sequence as a String. The class StringBuffer implements useful methods on mutable arrays of characters.

Source: Java Langage Specifications (p294, ou 328 du PDF)

Ce qui veut dire que si je sauve une variable de type String dans mon code, il est plus que probable que sa valeur reste en RAM même après si je perd la référence vers ce string. Je m'explique;

String s = "AAAAAAAA";

La chaine "AAAAAAA" se trouve quelque par en RAM, ça ne me surprend pas, on peut dire que ça me rassure même.

String s = "AAAAAAA"; 
s = "BBBBBBB";

Je pourrais m'attendre à ce que la chaine "AAAAAAAA" ne se trouve plus en RAM puisque j'ai changé sa valeur. Mais puisque les string sont immuables en java, il n'en n'est rien, la chaine est toujours en RAM.

Pour vérifier ceci, j'utilise deux programmes. Le premier, jmap, fourni avec mon JDK me permets d'obtenir un dump de la mémoire d'un processus. Une instruction de cette forme fait l'affaire;

jmap -dump:live,format=b,file=file.dump <pid>

Le second, hexdump, me permet de visualiser (en fait placer le contenu dans un fichier et l'éditer avec vi afin de me faciliter les recherches) le contenu de ce fichier "dump" ... il me reste à chercher les chaines de caractères qui m'intéressent.

hexdump -C file.dump > file.hexdump

J'écris un petit programme Java simple tel que;

import java.util.Scanner ; 

public class StringCharArray { 
		  
  private static Scanner clavier = new Scanner ( System.in ) ;  

    public static void main ( String[] args ) { 
      String s = "Password chaine 1"; 
      s = "Password chaine 222";
      char[] chars = 
        { 'P', 'A', 'S', 'S', 'W', 'O', 'R', 'D'};
      System.gc();
      chars = new char[] 
        { 'p', 'p', 'a', 'a', 's', 's', 'w', 'w', 'd', 'd'};
      clavier.next(); // wait
    }
}

Si ce que je pense est correct, je m'attend à trouver les "chaines"; "Password chaine 1", "Password chaine 222" et "ppaasswwoorrdd" mais pas "PASSWORD". Voici les screenshots que j'obtiens.

screenshot-dump-deux-1.png

screenshot-dump-deux-2.png

screenshot-dump-deux-4.png

screenshot-dump-deux-5.png

Ok, j'ai raison [1], mais c'est peut-être un coup de bol.

Je pourrais/devrais m'arrêter là mais pour être complet, je veux tester effectivement avec un GUI et un JPasswordField. J'écris un code permettant d'afficher ceci

  • la première zone est un JTextFiled,
  • la seconde un JPasswordFields,
  • le bouton "Get fields" permet d'associer les valeurs à des variables tandis que
  • le bouton "Garbage" repositionne ces variables à null et appelle le garbage collector

screenshot-gui.png

... et là, c'est moins concluant. J'entre les mêmes valeurs que dans le premier exemple et je fais passer le garbage collector. Le premier string disparait, ainsi que le premier char[] mais pas le deuxième string ni le deuxième char[].

J'en conclus que le garbage collector n'est pas passé. Par contre je devrais voir le premier string ... sinon je ne comprend pas l'utilité d'utiliser char[] dans ce cas.

Je suis preneur de toutes idées ...

... un jour plus tard ...

Dire qu'un string est immuable veut dire que je ne peux pas le modifier [2]. On n'imagine pas écrire du code comme ceci

String s = "un string";
//s[0] = 'T'; // compile pas : immuable
//s.charAt(0) = 'T'; // compile pas : immuable

Par contre je peux le faire avec un char[]. J'en conclus donc et c'est important que l'utilisation de getPAssword ne peut aller de paire qu'avec une mise à 0 des caractères après utilisation comme induit sur le site d'oracle . Du genre;

char[] password =  jPasswordFiled.getPassword();
// vérification de la validité de ce mot de passe
Arrays.fill(password, 0);

Voilà qui est clair maintenant ....

Notes

[1] Merci à mon collègue Nicolas pour le rappel de l'immuabilité des strings

[2] Remerci à Nicolas qui est au taquet