31
31
* @test
32
32
* @bug 8239893
33
33
* @summary Verify that handles for processes that terminate do not accumulate
34
- * @requires (os.family == "windows")
35
- * @run main/native CheckHandles
34
+ * @requires (( os.family == "windows") & (vm.compMode != "Xcomp") )
35
+ * @run main/othervm/ native -Xint CheckHandles
36
36
*/
37
37
public class CheckHandles {
38
38
@@ -43,46 +43,77 @@ public static void main(String[] args) throws Exception {
43
43
System .loadLibrary ("CheckHandles" );
44
44
45
45
System .out .println ("mypid: " + ProcessHandle .current ().pid ());
46
- long minHandles = Long .MAX_VALUE ;
47
- long maxHandles = 0L ;
46
+
47
+ // Warmup the process launch mechanism and vm to stabilize the number of handles in use
48
+ int MAX_WARMUP = 20 ;
49
+ long prevCount = getProcessHandleCount ();
50
+ for (int i = 0 ; i < MAX_WARMUP ; i ++) {
51
+ oneProcess ();
52
+ System .gc (); // an opportunity to close unreferenced handles
53
+ sleep (10 );
54
+
55
+ long count = getProcessHandleCount ();
56
+ if (count < 0 )
57
+ throw new AssertionError ("getProcessHandleCount failed" );
58
+ System .out .println ("warmup handle delta: " + (count - prevCount ));
59
+ prevCount = count ;
60
+ }
61
+ System .out .println ("Warmup done" );
62
+ System .out .println ();
63
+
64
+ prevCount = getProcessHandleCount ();
65
+ long startHandles = prevCount ;
66
+ long maxHandles = startHandles ;
48
67
int MAX_SPAWN = 50 ;
49
68
for (int i = 0 ; i < MAX_SPAWN ; i ++) {
50
- try {
51
- Process testProcess = new ProcessBuilder ("cmd" , "/c" , "dir" ).start ();
52
-
53
- Thread outputConsumer = new Thread (() -> consumeStream (testProcess .pid (), testProcess .getInputStream ()));
54
- outputConsumer .setDaemon (true );
55
- outputConsumer .start ();
56
- Thread errorConsumer = new Thread (() -> consumeStream (testProcess .pid (), testProcess .getErrorStream ()));
57
- errorConsumer .setDaemon (true );
58
- errorConsumer .start ();
59
-
60
- testProcess .waitFor ();
61
- System .gc ();
62
- outputConsumer .join ();
63
- errorConsumer .join ();
64
- long count = getProcessHandleCount ();
65
- if (count < 0 )
66
- throw new AssertionError ("getProcessHandleCount failed" );
67
- minHandles = Math .min (minHandles , count );
68
- maxHandles = Math .max (maxHandles , count );
69
- } catch (IOException | InterruptedException e ) {
70
- e .printStackTrace ();
71
- throw e ;
72
- }
69
+ oneProcess ();
70
+ System .gc (); // an opportunity to close unreferenced handles
71
+ sleep (10 );
72
+
73
+ long count = getProcessHandleCount ();
74
+ if (count < 0 )
75
+ throw new AssertionError ("getProcessHandleCount failed" );
76
+ System .out .println ("handle delta: " + (count - prevCount ));
77
+ prevCount = count ;
78
+ maxHandles = Math .max (maxHandles , count );
73
79
}
74
- final long ERROR_PERCENT = 10 ;
75
- final long ERROR_THRESHOLD = // 10% increase over min to passing max
76
- minHandles + ((minHandles + ERROR_PERCENT - 1 ) / ERROR_PERCENT );
80
+
81
+ System .out .println ("Processes started: " + MAX_SPAWN );
82
+ System .out .println ("startHandles: " + startHandles );
83
+ System .out .println ("maxHandles: " + maxHandles );
84
+
85
+ final float ERROR_PERCENT = 10.0f ; // allowable extra handles
86
+ final long ERROR_THRESHOLD = startHandles + Math .round (startHandles * ERROR_PERCENT / 100.0f );
77
87
if (maxHandles >= ERROR_THRESHOLD ) {
78
- System .out .println ("Processes started: " + MAX_SPAWN );
79
- System .out .println ("minhandles: " + minHandles );
80
- System .out .println ("maxhandles: " + maxHandles );
81
88
throw new AssertionError ("Handle use increased by more than " + ERROR_PERCENT + " percent." );
82
89
}
83
90
}
84
91
85
- private static void consumeStream (long pid , InputStream inputStream ) {
92
+ /**
93
+ * Start a single process and consume its output.
94
+ */
95
+ private static void oneProcess () {
96
+ try {
97
+
98
+ Process testProcess = new ProcessBuilder ("cmd" , "/c" , "dir" ).start ();
99
+
100
+ Thread outputConsumer = new Thread (() -> consumeStream (testProcess .getInputStream ()));
101
+ outputConsumer .setDaemon (true );
102
+ outputConsumer .start ();
103
+ Thread errorConsumer = new Thread (() -> consumeStream (testProcess .getErrorStream ()));
104
+ errorConsumer .setDaemon (true );
105
+ errorConsumer .start ();
106
+
107
+ testProcess .waitFor ();
108
+ outputConsumer .join ();
109
+ errorConsumer .join ();
110
+ } catch (IOException | InterruptedException e ) {
111
+ e .printStackTrace ();
112
+ throw new RuntimeException ("Exception" , e );
113
+ }
114
+ }
115
+
116
+ private static void consumeStream (InputStream inputStream ) {
86
117
BufferedReader reader = null ;
87
118
try {
88
119
int lines = 0 ;
@@ -102,4 +133,12 @@ private static void consumeStream(long pid, InputStream inputStream) {
102
133
}
103
134
}
104
135
}
136
+
137
+ private static void sleep (long millis ) {
138
+ try {
139
+ Thread .sleep (millis );
140
+ } catch (InterruptedException ie ) {
141
+ // ignore
142
+ }
143
+ }
105
144
}
0 commit comments