FAQ Java et le natif Consultez toutes les FAQ
Nombre d'auteurs : 11, nombre de questions : 31, dernière mise à jour : 28 février 2016 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum Java de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Comment accéder aux valeurs des variables d'environnement systèmes ?
- Comment accéder aux valeurs des variables d'environnement de la JVM ?
- Comment connaître la version de la JVM utilisée depuis le programme ?
- Comment connaître le système d'exploitation depuis le programme ?
- Comment connaître le nombre de processeurs disponibles depuis le programme ?
- Comment connaître la mémoire utilisée par notre application pendant son exécution ?
- Comment connaître la quantité de mémoire de la machine depuis le programme ?
- Comment connaître la charge processeur depuis le programme ?
- Comment exécuter un processus externe ?
- Comment communiquer avec un processus externe ?
- Pourquoi est-ce mon processus ne se termine jamais ?
- Pourquoi est-ce que je ne peux pas exécuter certain programmes (dir, redirections, etc.) ?
- Comment rediriger les entrées et sorties du processus vers des fichiers ?
- Comment lire/écrire du texte dans le presse-papier ?
- Comment lire/écrire une Image dans le presse-papier ?
- Comment connaitre la mémoire utilisable de la carte graphique ?
- Comment ouvrir une page web avec le navigateur par défaut en restant portable ?
- Comment ouvrir un fichier avec le programme par défaut en restant portable ?
- Comment ouvrir la boite de dialogue d'envoi d'email du logiciel de messagerie par défaut en restant portable ?
- Comment trouver le répertoire contenant le jar où est ma classe ?
- Comment créer un service Windows en Java ?
- Comment gérer facilement les préférences de l'utilisateur ?
- Où les préférences sont-elles enregistrées/lues ?
- Comment gérer les fermetures accidentelles (CTRL-C, kill -2, kill -15) ?
Avertissement : se baser sur les variables du système n'étant pas très portable, Java définit un certain nombre de variables de façon indépendante de la plateforme d'exécution via les variables d'environnement de la JVM ou via des classes dédiées.
L'accès aux variables d'environnement de la JVM se fait en invoquant la méthode statique getenv() de la classe utilitaire java.lang.System. Cette méthode donne accès aux valeurs de chacune des variables d'environnement systèmes telles qu'elles étaient définies au moment du lancement de la JVM.
Code Java : | Sélectionner tout |
String path = System.getenv("PATH");
À partir du JDK 5, la variante de la méthode getenv() sans argument permet de récupérer l'ensemble des variables d’environnement système.
Le programme suivant affiche la liste de toutes les variables et leur valeur :
Code Java : | Sélectionner tout |
1 2 3 4 5 | for (Map.Entry entry : System.getenv().entrySet()) { String cle = (String) entry.getKey(); String value = (String) entry.getValue(); System.out.println(cle + " = " + value); } |
L'accès aux variables d'environnement de la JVM se fait en invoquant la méthode statique getProperty() de la classe utilitaire java.lang.System. Cette méthode donne accès aux valeurs de chacune des variables d'environnement définies par la JVM.
Code Java : | Sélectionner tout |
1 2 3 4 | String repertoireCourant = System.getProperty("user.dir"); String repertoireJava = System.getProperty("java.home"); String repertoireUtilisateur = System.getProperty("user.home"); String os = System.getProperty("os.name"); |
La liste des toutes les variables d'environnement de la JVM est disponible en invoquant la méthode getProperties() de la classe java.lang.System. La liste complètes des variables qui sont sensée être toujours incluses dans l'objet retourné par cette méthode est indiquée dans sa page javadoc. Des variables supplémentaires peuvent cependant être présentes en fonction de l'origine de votre JVM, des bibliothèques tierces utilisées, des options du lancement du programme, etc.
Le programme suivant affiche la liste de toutes les variables et leur valeur :
Code Java : | Sélectionner tout |
1 2 3 4 5 | for (Map.Entry entry : System.getProperties().entrySet()) { String cle = (String) entry.getKey(); String valeur = (String) entry.getValue(); System.out.println(cle + " = " + valeur); } |
De nouvelles variables peuvent facilement être introduites dans la JVM lors du lancement du programme en les ajoutant à la ligne de commande :
Code Console : | Sélectionner tout |
java -DTEST="test" nom_programme
Ce qui rajoute dans la JVM une propriété système TEST ayant pour valeur "test".
Code Java : | Sélectionner tout |
String valeur = System.getProperty("TEST"); // Contiendra "test".
Il est également possible d’utiliser les methodes setProperty() ou setProperties() de la classe java.lang.System pour modifier ces variables durant l’exécution du programme.
Il peut être parfois intéressante de connaitre la version de la JVM en cours d’exécution pour permettre de bénéficier de fonctionnalités mineures qui ont été introduites lors de sous-versions intermédiaires, de vérifier si certains bugs connus ont été corrigés ou tout simplement d'informer l'utilisateur qu'il est temps pour lui de mettre à jour Java sur sa machine.
Propriétés systèmes
Pour cela, il suffit de consulter les variables d'environnement initialisées par la JVM :
- java.version - Version de Java ;
- java.vendor - Distributeur de votre version de Java ;
- java.vendor.url - URL du site web du distributeur ;
- java.vm.name - Le nom de la VM ;
- java.vm.version - La version de la VM ;
- java.vm.version - Le distributeur de la VM ;
- java.vm.specification.name - Le nom des spécifications la VM ;
- java.vm.specification.version - La version des spécifications de la VM ;
- java.vm.specification.version - Le distributeur des spécifications de la VM.
Code Java : | Sélectionner tout |
String version = System.getProperty("java.vm.version");
MXBeans
À partir du JDK 5, vous pouvez interroger les beans de gestion de la JVM. La méthode statique getRuntimeMXBean() de la classe fabrique java.lang.management.ManagementFactory retourne un bean de type java.lang.management.RuntimeMXBean sur lequel il est possible d'invoquer les méthodes retournant des informations sur la JVM :
- getName() - L'identifiant de la JVM dans laquelle tourne votre code ;
- getVmName() - Le nom de la VM ;
- getVmVersion() - La version de la VM ;
- getVmVendor - Le distributeur de la VM ;
- getSpecName() - Le nom des spécifications la VM ;
- getSpecVersion() - La version des spécifications de la VM ;
- getSpecVendor() - Le distributeur des spécifications de la VM.
Code Java : | Sélectionner tout |
1 2 | RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); String version = runtimeMxBean.getVmVersion()); |
Bien que Java soit conçu pour fonctionner indépendamment du système, il est parfois utile de savoir lequel exécute notre programme. Cela permet, par exemple, de choisir si l'on doit exécuter Mozilla, Safari ou plutôt Chrome ou Edge.
Propriétés systèmes
Pour cela, il suffit de consulter les variables d'environnement initialisées par la JVM :
- os.name - Nom du système d'exploitation ;
- os.version - Version du système d'exploitation ;
- os.arch - Architecture du système d'exploitation.
Code Java : | Sélectionner tout |
String nom = System.getProperty("os.name");
MXBeans
À partir du JDK 5, vous pouvez interroger les beans de gestion de la JVM. La méthode statique getOperatingSystemMXBean() de la classe fabrique java.lang.management.ManagementFactory retourne un bean de type java.lang.management.OperatingSystemMXBean sur lequel il est possible d'invoquer les méthodes :
- getName() - Nom du système d'exploitation ;
- getVersion() - Version du système d'exploitation ;
- getArch() - Architecture du système d'exploitation.
Code Java : | Sélectionner tout |
1 2 | OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean(); String nom = osMxBean.getName(); |
La connaissance du nombre de CPU de la machine peut être utile dans certains cas ; par exemple, pour savoir combien de threads maximum on peut lancer en concurrence sans trop affecter les performances générales de la machine.
Propriétés systèmes
À partir du JDK 1.4, cette information est disponible en invoquant la méthode availableProcessors() de la classe java.lang.Runtime :
Code Java : | Sélectionner tout |
int nbProc = Runtime.getRuntime().availableProcessors();
MXBeans
À partir du JDK 5, vous pouvez interroger les beans de gestion de la JVM. La méthode statique getOperatingSystemMXBean() de la classe fabrique java.lang.management.ManagementFactory retourne un bean de type java.lang.management.OperatingSystemMXBean sur lequel il est possible d'invoquer la méthode getAvailableProcessors().
Code Java : | Sélectionner tout |
1 2 | OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean(); int nbProc = osMxBean.getAvailableProcessors(); |
Ici, nous allons parler de la quantité de mémoire actuellement allouée par l'utilisation de la JVM et par votre application.
java.lang.Runtime
La mémoire totale de la JVM, de même que la mémoire libre de la JVM peuvent être récupérées en invoquant les méthodes freeMemory() et totalMemory() de la classe java.lang.Runtime. La mémoire totale est la quantité de mémoire qui a été réservée auprès du système d'exploitation tandis que la mémoire libre est la quantité de mémoire libre utilisable avant que la JVM n'alloue encore de la mémoire auprès du système.
Code Java : | Sélectionner tout |
1 2 3 | long memoireLibreJVM = Runtime.getRuntime().freeMemory(); long memoireTotaleJVM = Runtime.getRuntime().totalMemory(); long memoireUtiliseeJVM = memoireTotaleJVM - memoireLibreJVM; |
À partir du JDK 1.4, il est de plus possible de récupérer la quantité maximale de mémoire que la JVM est autorisée à réserver auprès du système d'exploitation en invoquant la méthode maxMemory() :
Code Java : | Sélectionner tout |
long memoireMaxJVM = Runtime.getRuntime().maxMemory();
MXBeans
À partir du JDK 5, vous pouvez interroger les beans de gestion de la JVM. La méthode statique getMemoryMXBean() de la classe fabrique java.lang.management.ManagementFactory retourne un bean de type java.lang.management.MemoryMXBean. Ce bean dispose des méthodes :
- getHeapMemoryUsage() - Contient le détail de la mémoire utilisée par votre application ;
- getNonHeapMemoryUsage() - permet de surveiller la mémoire utilisée pour la JVM elle-même (et non pas par votre application).
Chacune de ces méthode retourne un objet de type java.lang.management.MemoryUsage disposant des methodes suivantes :
- getInit() - La quantité de mémoire qui a été initialement requise par la JVM. Retourne -1 si cette valeur n'est pas définie ; généralement 0, sauf si l'on a utilisé l'option -Xms de la JVM ;
- getUsed() - La mémoire allouée actuellement utilisée par votre application ;
- getCommitted() - La mémoire réservée par la JVM auprès du système d'exploitation ;
- getMax() - Le maximum de mémoire allouable (modifiable avec l'option -Xmx de la JVM). Si l'application utilise plus de mémoire cela génèrera une erreur de type OutOfMemoryError. Retourne -1 si cette valeur n'est pas définie ;
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 | MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean(); MemoryUsage memoireTas = memoryMxBean.getHeapMemoryUsage(); long tasInitial = memoireTas.getInit(); long tasUtilise = memoireTas.getUsed(); long tasReserve = memoireTas.getCommitted(); long tasMax = memoireTas.getMax(); MemoryUsage memoirePasTas = memoryMxBean.getNonHeapMemoryUsage(); [...] |
Ici, nous allons parler de la mémoire physique (la RAM sur la machine), ainsi que de la mémoire d’échange (la mémoire allouée dans un fichier d’échange -Windows- ou sur une partition spécialise swap -Linux-) et de la mémoire virtuelle de la machine (mémoire physique + la mémoire d’échange).
À partir du JDK 5, il est possible de récupérer les informations concernant la mémoire physique de la JVM en manipulant une instance l'interface com.sun.management.OperatingSystemMXBean. Cette classe fait normalement partie de l'API privée du JDK mais est, depuis le JDK 8, marquée de l'annotation @Exported qui indique qu'elle est utilisable publiquement. Ce bean dispose des méthodes suivantes qui peuvent être utilisées pour retourner des informations sur la mémoire de votre machine :
- getTotalPhysicalMemorySize() - La mémoire physique totale de votre machine ;
- getFreePhysicalMemorySize - La mémoire physique libre de votre machine ;
- getTotalSwapSpaceSize - La mémoire d’échange totale de votre machine ;
- getFreeSwapSpaceSize - La mémoire d’échange libre de votre machine ;
- getCommittedVirtualMemorySize - La mémoire virtuelle de votre machine réservée pour la JVM. Retourne -1 si cette valeur n'est pas définie ;
Code Java : | Sélectionner tout |
1 2 3 4 | OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean(); com.sun.management.OperatingSystemMXBean privateOsMxBean = (com.sun.management.OperatingSystemMXBean) osMxBean; long memoireTotale = privateOsMxBean.getFreePhysicalMemorySize()); long memoireLibre = privateOsMxBean.getTotalPhysicalMemorySize()); |
Attention : bien que publiquement utilisable, cette classe peut devenir privée ou être totalement retirée lors de futures versions du JDK.
Autres
La bibliothèque tierce SIGAR (System Information Gatherer And Reporter) fournit une API portable permettant d’accéder aux ressources systèmes.
À partir du JDK 5, il est possible de récupérer les informations concernant la mémoire physique de la JVM en manipulant une instance l'interface com.sun.management.OperatingSystemMXBean. Cette classe fait normalement partie de l'API privée du JDK mais est, depuis le JDK 8, marquée de l'annotation @Exported qui indique qu'elle est utilisable publiquement. Ce bean dispose des méthodes suivantes qui peuvent être utilisées pour retourner des informations sur l'occupation CPU de votre machine :
- getProcessCpuLoad() - Le pourcentage de charge CPU pris par la JVM.
- getSystemCpuLoad() - Le pourcentage de charge CPU global sur le système ;
- getProcessCpuTime() - Le temps CPU depuis lequel la JVM est active en nanosecondes.
Code Java : | Sélectionner tout |
1 2 3 | OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean(); com.sun.management.OperatingSystemMXBean privateOsMxBean = (com.sun.management.OperatingSystemMXBean) osMxBean; double chargeCpuJvm = privateOsMxBean.getProcessCpuLoad(); |
Attention : bien que publiquement utilisable, cette classe peut devenir privée ou être totalement retirée lors de futures versions du JDK.
Autres
La bibliothèque tierce SIGAR (System Information Gatherer And Reporter) fournit une API portable permettant d’accéder aux ressources systèmes.
Note : la notion d’exécutable est très variable d'un système d'exploitation à un autre. Sur Microsoft Windows, il s'agit principalement de l'extension que porte le fichier (.exe, .com, etc.) tandis que sous les systèmes de type UNIX, il s'agit principalement de droits attachés au fichier lui-même. Sur la plupart des systèmes, la résolution de l'emplacement du programme invoqué est fortement dépendant de la configuration de la variable environnement système PATH. Sur Microsoft Windows, le répertoire courant est implicitement en tête de PATH lors de la recherche de la résolution. Lors de l'invocation d'un exécutable sous Microsoft Windows, il n'est généralement pas besoin de spécifier l'extension du fichier ; cela se fait généralement de manière implicite.
Méthode exec()
L'exécution d'un programme externe se peut se faire grâce à la méthode exec() de la classe java.lang.Runtime.
Code Java : | Sélectionner tout |
1 2 3 4 5 | try { Process process = Runtime.getRuntime().exec("commande paramétrée"); } catch (IOException e) { // Traitement des erreurs. } |
ProcessBuilder
À partir du JDK 5, il est possible d'utiliser la classe java.lang.ProcessBuilder pour monter manuellement un processus externe, ce qui permet une approche plus fine de la construction de la commande à exécuter.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | try { ProcessBuilder builder = new ProcessBuilder("commande", "parametre1", "parametre2", [...], "parametreN"); // Modification du répertoire de travail. builder.directory(repertoireDeTravail); // Modification de l’enveloppe des variables d'environnement. builder.environment().put("TEST", "test"); // Lancement du processus. Process process = builder.start(); } catch (IOException e) { // Traitement des erreurs. } |
Il est possible de communiquer avec des processus externes grâce aux méthodes de l'objet java.lang.Process que vous obtenez en lançant la commande :
- destroy() - Pour tuer l'application fille ;
- waitFor() - Pour attendre la fin de l'application fille. Cette méthode est bloquante et donc gèle l'exécution du thread courant. Il faudra donc faire attention à lancer le processus dans une tache de fond pour éviter le bloquer des threads évènementiels tels que l'EDT de AWT/Swing ou le JavaFX Application Thread. Depuis le JDK 8, il existe une variante de cette méthode permettant de spécifier un timeout qui permet au thread courant de reprendre la main après un certain temps d'attente si le processus ne se termine pas.
- getOutputStream(), getInputStream() et getErrorStream() - Ces méthodes permettent de communiquer avec l'application :
- getOutputStream() - Un flux de sortie permettant d’écrire dans l’entrée standard (in) du processus ;
- getInputStream() - Un flux d’entrée permettant de lire le contenu de la sortie standard (out) du processus ;
- getErrorStream() - Un flux d’entrée permettant de lire le contenu de la sortie d'erreur standard (err) du processus ;
- exitValue() - Pour connaitre l'état de sortie ou code d'erreur retour de l'application. Cette méthode est non-bloquante mais peut lever une exception de type java.lang.IllegalThreadStateException si le processus n'est pas encore terminé au moment auquel vous invoquez cette méthode.
Il y a plusieurs raisons pour lesquelles votre processus peut ne jamais se terminer et votre waitFor() ne jamais retourner de valeur :
En attente de saisie utilisateur
Votre processus est peut-être en mode interactif et il attend peut-être une saisie de votre part. Vous pouvez invoquer sa méthode process.getOutputStream() ce qui vous permet d’écrire dans son entrée standard.
Code Java : | Sélectionner tout |
1 2 3 4 | try (OutputStream output = process.getOutputStream()) { // Ecrire dans l'entree standard du processus. [...] } |
Tampon de sortie pleins
Les tampons qui stockent les valeurs imprimées sur la sortie standard et la sortie d'erreur standard de l'application externe peuvent être pleins. Cette erreur se produit assez régulièrement avec les applications qui ont beaucoup de sortie sur la console : lors qu'il est lancé depuis Java, le processus ne peut plus écrire dans les tampons et se bloque tant que les tampons ne sont pas vidés de leur contenu. Vous, en tant que programmeur, devez faire le nécessaire pour "consommer" le contenu de ces deux sorties.
Par exemple, le code suivant va consommer le contenu de chacun des flux de sortie standard de l'application et va les imprimer sur les flux appropriés de la console.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | Process process = [...] Thread outThread = new Thread(new StreamConsumer(process.getInputStream(), System.out)); Thread errThread = new Thread(new StreamConsumer(process.getErrorStream(), System.err)); outThread.start(); errThread.start(); int result = process.waitFor(); [...] // Consomme le contenu d'un flux et le redirige vers un autre si necessaire. private static class StreamConsumer implements Runnable { private InputStream source; private PrintStream target; public StreamConsumer(InputStream source, PrintStream target) { this.source = source; this.target = target; } @Override public void run() { try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(source))) { String line = null; while ((line = reader.readLine()) != null) { if (target != null) { target.println(line); } } } catch (Exception ex) { ex.printStackTrace(); } finally { source = null; target = null; } } } |
Ici, nous consommons chaque flux dans son propre thread en parallèle.
Sur certains systèmes d'exploitation, ce que l'utilisateur croit être des programmes sont en fait des commandes de l’interpréteur de commande. Par exemple, sous Microsoft Windows, dir, qui permet de lister le contenu des répertoire, est en fait une commande de l’interpréteur cmd.exe plutôt qu'un programme à part entière. Or, ni Runtime::exec(), ni ProcessBuilder::start() ne sont des interpréteurs de commandes ; ils permettent juste d'invoquer des programmes qui se situent sur le PATH de votre ordinateur.
Ainsi, sur une machine Windows, on tente d’exécuter le processus suivant pour avoir le listing réduit du contenu d'un répertoire :
Code Java : | Sélectionner tout |
Process process = Runtime.getRuntime().exec("dir /b");
À l’exécution, ceci lèvera une exception de type java.io.IOException contenant le message "Cannot run program "dir": CreateProcess error=2, The system cannot find the file specified.". En effet, il n'existe pas de programme dir.exe sur le PATH.
Ici, pour invoquer la commande dir, il nous faut invoquer à la place l’interpréteur de commande cmd.exe en lui passant en paramètre les bons arguments :
Code Java : | Sélectionner tout |
Process process = Runtime.getRuntime().exec("cmd /c dir /b");
De la même manière, invoquer la commande suivante qui contient une redirection n'aura pas l'effet escompté :
Code Java : | Sélectionner tout |
Process process = Runtime.getRuntime().exec("java -version 2> foo.txt");
Le but était ici de recopier la version de l’interpréteur java dans un fichier foot.txt ; en effet java -version imprime des informations sur la sortie d'erreur standard du programme ce que nous essayons de rediriger avec l'argument 2>. Mais en fait, pour arriver à faire cette redirection, il vous faudra invoquer l’interpréteur de commande approprié pour votre système d'exploitation :
Code Java : | Sélectionner tout |
1 2 3 | Process process = Runtime.getRuntime().exec("cmd /c java -version 2> foo.txt"); // Ou : Process process = Runtime.getRuntime().exec("sh -c \"java -version 2> foo.txt\""); |
En créant votre processus avec ProcessBuilder vous pouvez spécifier une redirection pour les flux d’entrée standard, de sortie standard et d'erreur standard en invoquant ses méthodes :
- redirectOutput() - Redirige la sortie standard vers un fichier ;
- redirectInput() - Redirige la sortie d'erreur standard vers un fichier ;
- redirectError() - Permet de remplir l’entrée standard avec le contenu d'un fichier existant.
Code Java : | Sélectionner tout |
1 2 3 4 | ProcessBuilder builder = new ProcessBuilder("java", "-version"); builder.redirectError(new File("foo.txt")); Process process = builder.start(); int result = process.waitFor(); |
Ici, nous redirigeons la sortie d'erreur standard de la commande dans un fichier nommé foo.txt ; en effet java -version imprime des informations sur la sortie d'erreur standard du programme.
L'accès au presse-papier se fait grâce à la classe awt.datatransfer.Clipboard disponible dans la boite à outils java.awt.Toolkit.
Lire du texte :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); try { // Vérification que le contenu est de type texte. if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) { String txt = (String) t.getTransferData(DataFlavor.stringFlavor); } } catch (UnsupportedFlavorException | IOException | IllegalStateException ex) { // Le presse papier n'est peut-etre pas disponible. // Ou une erreur peut survenir lors du transfert. // Gestion de l'erreur. [...] } |
Écrire du texte :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 | try { StringSelection ss = new StringSelection("Mon Texte"); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null); } catch (IllegalStateException ex) { // Le presse papier n'est peut-etre pas disponible. // Gestion de l'erreur. [...] } |
À noter que, sous Microsoft Windows, une exception de type IllegalStateException peut être lancée si le presse-papier est vide.
Le principe est le même que pour l'écriture ou la lecture de texte.
Acquérir une image :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); try { if (t != null && t.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image = (Image) t.getTransferData(DataFlavor.imageFlavor); return image; } } catch (UnsupportedFlavorException | IOException | IllegalStateException ex) { // Gestion de l'erreur. [...] } |
Lire une image :
Ici, la seule difficulté viens du fait qu'il n'existe pas d'image implémentant l'interface java.awt.datatransfer.Transferable. Cette difficulté est toute relative car la création d'une telle classe tient en quelques lignes :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public final class TransferableImage implements Transferable { private final Image image; public TransferableImage(Image uneImage) { image = uneImage; } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (!isDataFlavorSupported(flavor)) { throw new UnsupportedFlavorException(flavor); } return image; } @Override public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[]{DataFlavor.imageFlavor}; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return DataFlavor.imageFlavor.equals(flavor); } } |
Il nous suffit alors d'utiliser cette nouvelle classe pour écrire notre image sur le presse-papier :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 | try { TransferableImage transferable = new TransferableImage(image); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(transferable, null); } catch (IllegalStateException ex) { // Gestion de l'erreur. [...] } |
Voici une méthode permettant de récupérer la mémoire vidéo accélérée disponible (en Mo) pour la carte graphique :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | public int getAvailableVRAM(){ // Obtenir le type d'environnement graphique sous lequel tourne la JVM. GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); // Obtenir le périphérique d'affichage (carte graphique). GraphicsDevice device = environment.getDefaultScreenDevice(); // Calcule le nombre de Méga Octets libres dans la carte graphique. int bytes = device.getAvailableAcceleratedMemory(); int mbytes = bytes /1048576; return mbytes; } |
Attention : la méthode getAvailableAcceleratedMemory() peut retourner un nombre négatif si la quantité de vidéo accélérée disponible est indéterminée.
Avant le JDK 6
Vous pouvez utiliser l'api JDIC. Cette api permet une meilleure intégration au système tout en conservant la portabilité. Ainsi, vous pourrez faire :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 | try { Desktop.browse(url); } catch (Exception ex) { // Gestion de l'erreur. [...] } |
Il faut penser à ajouter jdic.dll dans le CLASSPATH pour qu'il soit utilisable. Il suffit normalement de le mettre au même niveau que votre application et la JVM le trouvera.
JDK 6
À partir du JDK 6, cette fonctionnalité a été intégré en standard via la classe java.awt.Desktop qui possède un comportement similaire. Toutefois, étant donné qu'il s'agit d'une fonctionnalité dépendant du système d'exploitation et/ou du gestionnaire de fenêtre, elle n'est pas forcément disponible sur tous les systèmes et nécessite des vérifications préalables sous peine de lever une exception de type UnsupportedOperationException.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | URI uri = [...] // On vérifie que la classe Desktop soit bien supportée : if (Desktop.isDesktopSupported()) { // On récupère l'instance du desktop : Desktop desktop = Desktop.getDesktop(); // On vérifie que la fonction browse est bien supportée : if (desktop.isSupported(Desktop.Action.BROWSE)) { // Et on lance l'application associé au protocole : try { desktop.browse(uri); } (IOException ex) { // Gestion de l'erreur. [...] } } } |
À noter qu'il est également possible d'utiliser cette méthode pour ouvrir des URI concernant des protocoles autres que le protocole HTTP (ex : FTP, etc.).
Avant le JDK 6
Vous pouvez utiliser l'api JDIC. Cette api permet une meilleure intégration au système tout en conservant la portabilité. Ainsi, vous pourrez faire :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 | File fichier = [...] try { Desktop.open(fichier); } catch (DesktopException ex) { // Gestion de l'erreur : [...] } |
Il faut penser à ajouter jdic.dll dans le CLASSPATH pour qu'il soit utilisable. Il suffit normalement de le mettre au même niveau que votre application et la JVM le trouvera.
JDK 6
À partir du JDK 6, cette fonctionnalité a été intégré en standard via la classe java.awt.Desktop qui possède un comportement similaire. Toutefois, étant donné qu'il s'agit d'une fonctionnalité dépendant du système d'exploitation et/ou du gestionnaire de fenêtre, elle n'est pas forcément disponible sur tous les systèmes et nécessite des vérifications préalables sous peine de lever une exception de type UnsupportedOperationException.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | File fichier = [...] // On vérifie que la classe Desktop soit bien supportée : if (Desktop.isDesktopSupported()) { // On récupère l'instance du desktop : Desktop desktop = Desktop.getDesktop(); // On vérifie que la fonction open est bien supportée : if (desktop.isSupported(Desktop.Action.OPEN)) { // Et on lance l'application associé au fichier pour l'ouvrir : try { desktop.open(fichier); } (IOException ex) { // Gestion de l'erreur. [...] } } } |
À noter qu'il est également possible d'utiliser les méthodes edit() et print() de la même manière, ce qui a respectivement pour effet d'ouvrir le fichier en édition et de l'imprimer, toujours en utilisant les programmes par défaut.
Avant le JDK 6
Vous pouvez utilisez l'api JDIC. Cette api permet une meilleure intégration au système tout en conservant la portabilité. Ainsi, vous pourrez faire :
Code Java : | Sélectionner tout |
1 2 3 4 5 6 | try { Desktop.mail(); } catch (Exception ex) { // Gestion de l'erreur. [...] } |
JDK 6
Avec le JDK 6, cette fonctionnalité a été intégré en standard via la classe java.awt.Desktop qui possède un comportement similaire. Toutefois, étant donné qu'il s'agit d'une fonctionnalité dépendant du système d'exploitation et/ou du gestionnaire de fenêtre, elle n'est pas forcément disponible sur tous les systèmes et nécessite des vérifications préalables sous peine de lever une exception de type UnsupportedOperationException.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | if (Desktop.isDesktopSupported()) { // On récupère l'instance du desktop : Desktop desktop = Desktop.getDesktop(); // On vérifie que la fonction mail est bien supportée : if (desktop.isSupported(Desktop.Action.MAIL)) { try { // Et on ouvre un nouveau courriel : desktop.mail(); } catch (IOException ex) { // Gestion de l'erreur. [...] } } } |
À noter qu'il est également possible d'utiliser la méthode mail() en lui donnant en paramètre une URI utilisant le protocole MAILTO pour spécifier des paramètre avancés (nom du destinataire, copie, sujet, contenu du message, etc.).
Le bout de code suivant permet de retrouver le répertoire contenant le fichier JAR dans lequel se situe la classe courante. Si la classe n'est pas dans un JAR, le répertoire sera celui présent dans le CLASSPATH. Par exemple, si la classe est dans C:\sources\java\lang\Object.class alors le répertoire trouvé sera C:\sources.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | Class sourceClass = [...] try { String path = "/" + sourceClass.getName().replace('.', '/') + ".class"; URL url = getClass().getResource(path); path = URLDecoder.decode(url.toString(), "UTF-8"); // Suppression de la classe ou du JAR du chemin de l'url. int index = path.lastIndexOf("/"); path = path.substring(0, index); if (path.startsWith("jar:file:")) { // Suppression du protocole jar:file: de l'url d'un JAR // ainsi que du path de la classe dans le jar index = path.indexOf("!"); path = path.substring(9, index); } else { // Suppresion du file: de l'url si c'est une classe en dehors d'un JAR // et suppression du path du package s'il est présent. path = path.substring(5, path.length()); Package pack = getClass().getPackage(); if (null != pack) { String packPath = pack.toString().replace('.', '/'); if (path.endsWith(packPath)) { path = path.substring(0, (path.length() - packPath.length())); } } } System.out.println("Répertoire contenant la classe: " + path); } catch (UnsupportedEncodingException ex) { // Gestion de l'erreur. [...] } |
Un service Microsoft Windows est un programme qui est soit démarré au démarrage du système soit qui peut être démarré depuis le programme "Services" fournit avec Windows (NT, 2000, XP ou supérieur).
Pour utiliser un programme Java en tant que service pour Microsoft Windows, il existe divers projets projet open-source ou commerciaux qui permettent de créer un lanceur natif supportant l'architecture des services :
- JavaService - Open-source ;
- Apache Commons Daemon - Open-source ;
- NSSM - the Non-Sucking Service Manager - Open-source ;
- WinRun4J - Open-Source ;
- Tanuki Software Java Service Wrapper - Commercial ;
- etc.
Certains de ces outils peuvent également servir à créer des daemons pour UNIX ou Linux.
À noter toutefois qu'il n'est généralement pas possible d'avoir une interface graphique pour une application Java qui tournerait comme un service Windows.
La classe abstraite Preferences du package java.util.prefs permet d'enregistrer facilement certaines données. Les préférences associent à une clé de type String à une valeur, comme un dictionnaire.
Niveaux de préférences
Plusieurs niveaux de préférences peuvent être définis selon qu'on désire sauvegarder une donnée pour un utilisateur ou pour le système. Ces niveaux sont accessibles grâce aux méthodes statiques de la classe Preferences.
- Preferences.systemRoot() - Préférences globales du système ;
- Preferences.systemNodeForPackage() - Préférences du système pour le package d'une classe donnée ;
- Preferences.userRoot() - Préférences globales de l'utilisateur ;
- Preferences.userNodeForPackage() - Préférences globales de l'utilisateur pour le package dune classe donnée.
Lecture
La lecture se fait grâce aux méthodes getXXX() de la classe Preferences. Ces méthode prennent une valeur par défaut qui sera retournée dans le cas où la clé se trouve être absente du stockage.
Code java : | Sélectionner tout |
1 2 3 4 | Preferences prefs = Preferences.userRoot(); String unString = prefs.get("clé","une valeur par défaut s'il n'y a pas de valeur"); // On doit toujours spécifier une valeur par défaut. // On peut aussi récupérer d'autres types primitifs int unInt = prefs.getInt("cléInt", 123); |
Écriture
L’écriture se fait grâce aux méthodes putXXX() de la classe Preferences.
Code java : | Sélectionner tout |
1 2 3 | Preferences prefs = Preferences.userRoot(); prefs.put("clé", "valeur"); prefs.putInt("cléInt", 456); |
Il n'est pas possible de stocker la valeur null dans les préférences sous peine de lever une exception de type NullPointerException ; vous devrez vous rabattre sur la chaine vide "".
De plus, de manière générale, vous ne pourrez pas enregistrer de préférences systèmes si votre compte utilisateur ne bénéficie pas des droits appropriés sur la machine. Invoquer les méthodes d’écriture ne lèvera pas d'erreur mais aucune valeur sera sauvegardée.
Les implémentations des préférences dépendent du système (registres, fichiers, SGBD, etc.), mais ceci est généralement invisible pour l'utilisateur. Cependant, il peut être parfois cessionnaire d’accéder directement à leur emplacement de stockage. Voici quelques uns des emplacements par défaut pour les systèmes les plus fréquemment utilisés :
Linux
Les préférences sont stockées sous la forme de fichiers texte au format XML :
- Système - Dans /etc/.java/.systemPrefs/ et ses sous-répertoires ;
- Utilisateur - Dans ~/.java/.userPrefs/ et ses sous-répertoires.
Microsoft Windows
Les préférences sont stockées sous la forme de clés dans le registre :
- Système - Sous la clé HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs\ ainsi que ses sous-clés ;
- Utilisateur - Sous la clé HKEY_CURRENT_USER\SOFTWARE\JavaSoft\Prefs\ ainsi que ses sous-clés. De même que sous la clé HKEY_USERS\<utilisateur>\SOFTWARE\JavaSoft\Prefs\ ainsi que ses sous-clés.
Apple Mac OS X
Les préférences sont stockées sous la forme de fichiers plist binaires pour chaque package :
- Système - Dans /Library/Preferences/ ;
- Utilisateur - Dans ~/Library/Preferences/.
CTRL-C, kill -2, kill -15 et autres sont des méthodes permettant d'arrêter l'exécution du programme sans lui demander son avis. Pourtant, il est parfois nécessaire de faire au moins quelques instructions capitales telles que la fermeture de flux de fichier, d'une connexion réseaux ou une sauvegarde rapide. Pour se faire il est possible de définir d'invoquer la methode addShutdownHook() de la classe java.util.Runtime. Cette méthode permet d'enregistrer un thread qui sera exécuté à la réception du signal de fin d'exécution.
Code Java : | Sélectionner tout |
1 2 3 4 5 6 7 | Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { // Actions à effectuer lors de la fermeture de la JVM. [...] } }); |
Attention :ce traitement final sera également exécuté lors de l'arrêt normal de l'application.
Note : cette astuce ne marche malheureusement pas pour le code kill -9.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.