1 package net.bull.javamelody.internal.model;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.lang.management.ManagementFactory;
7 import java.lang.management.RuntimeMXBean;
8 import java.nio.charset.Charset;
9 import java.util.Locale;
10 import java.util.StringTokenizer;
11
12 import net.bull.javamelody.internal.common.InputOutput;
13
14 /**
15  * PID du process java.
16  */

17 public final class PID {
18     private PID() {
19         super();
20     }
21
22     /**
23      * @return PID du process java
24      */

25     public static String getPID() {
26         String pid = System.getProperty("pid");
27         if (pid == null) {
28             // first, reliable with sun jdk (http://golesny.de/wiki/code:javahowtogetpid)
29             final RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean();
30             final String processName = rtb.getName();
31             /* tested on: */
32             /* - windows xp sp 2, java 1.5.0_13 */
33             /* - mac os x 10.4.10, java 1.5.0 */
34             /* - debian linux, java 1.5.0_13 */
35             /* all return pid@host, e.g 2204@antonius */
36
37             if (processName.indexOf('@') != -1) {
38                 pid = processName.substring(0, processName.indexOf('@'));
39             } else {
40                 pid = getPIDFromOS();
41             }
42             System.setProperty("pid", pid);
43         }
44         return pid;
45     }
46
47     static String getPIDFromOS() {
48         String pid;
49         // following is not always reliable as is (for example, see issue 3 on solaris 10
50         // or http://blog.igorminar.com/2007/03/how-java-application-can-discover-its.html)
51         // Author: Santhosh Kumar T, https://github.com/santhosh-tekuri/jlibs, licence LGPL
52         // Author getpids.exe: Daniel Scheibli, http://www.scheibli.com/projects/getpids/index.html, licence GPL
53         final String[] cmd;
54         File tempFile = null;
55         Process process = null;
56         try {
57             try {
58                 if (!System.getProperty("os.name").toLowerCase(Locale.ENGLISH)
59                         .contains("windows")) {
60                     cmd = new String[] { "/bin/sh""-c""echo $$ $PPID" };
61                 } else {
62                     // getpids.exe is taken from http://www.scheibli.com/projects/getpids/index.html (GPL)
63                     tempFile = File.createTempFile("getpids"".exe");
64
65                     // extract the embedded getpids.exe file from the jar and save it to above file
66                     extractGetPid(tempFile);
67                     cmd = new String[] { tempFile.getAbsolutePath() };
68                 }
69                 process = Runtime.getRuntime().exec(cmd);
70                 final String processOutput = InputOutput.pumpToString(process.getInputStream(),
71                         Charset.defaultCharset());
72                 final StringTokenizer stok = new StringTokenizer(processOutput);
73                 stok.nextToken(); // this is pid of the process we spanned
74                 pid = stok.nextToken();
75
76                 // waitFor nécessaire sous windows server 2003
77                 // (sinon le fichier temporaire getpidsxxx.exe n'est pas effacé)
78                 process.waitFor();
79             } finally {
80                 if (process != null) {
81                     // évitons http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6462165
82                     process.getInputStream().close();
83                     process.getOutputStream().close();
84                     process.getErrorStream().close();
85                     process.destroy();
86                 }
87                 if (tempFile != null && !tempFile.delete()) {
88                     tempFile.deleteOnExit();
89                 }
90             }
91         } catch (final InterruptedException | IOException e) {
92             pid = e.toString();
93         }
94         return pid;
95     }
96
97     private static void extractGetPid(File tempFile) throws IOException {
98         try (InputStream input = PID.class
99                 .getResourceAsStream("/net/bull/javamelody/resource/getpids.exe")) {
100             InputOutput.pumpToFile(input, tempFile);
101         }
102     }
103 }
104