Hi Pablo,
today I've made a real progress, as it seems.
I've been using the Runtime.exec() method instead of using the ProcessBuilder (until I found that exec() ist just a wrapper around the Processbuilder).
I've tried to destroy() processes explicitly (after they have terminated).
All to no avail :-(
Anyway, the only thing left to try was to see if the Garbage Collector does more than just to clean up memory.
The hint that made me try this stated that the GC not only cleans up but also closes open files (if the object to clean out happens to be an unreferenced file object).
Hence that could work for process handles as well.
After changing my test program:
import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.text.*;
import java.lang.reflect.*;
import java.util.concurrent.TimeUnit;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
public class StartPS
{
static Long STARTTIME_JITTER = 5000L;
synchronized public static HashMap<String,Long> getStartTimes()
{
HashMap<String,Long> result = new HashMap<String, Long>();;
final File tmp_file = new File("/tmp/starttimes.out");
String tmpfilename = null;
try {
tmpfilename = tmp_file.getCanonicalPath();
} catch (Exception e) {}
try {
ProcessBuilder pb = new ProcessBuilder(".\\winps.exe");
pb.redirectOutput(new File(tmpfilename));
pb.redirectErrorStream(true);
Process p = pb.start();
p.getOutputStream().close();
p.getInputStream().close();
p.getErrorStream().close();
try {
p.waitFor();
} catch (InterruptedException ie) {
// maybe some cleanup here
}
try {
while (p.isAlive()) { // <- most likely unnecessary ;-)
Thread.sleep(100);
p.destroy();
System.gc();
}
p = null; // should help the garbage collector (eliminates a reference to the object p points to)
System.gc(); // <- most likely the key to success !
} catch (Exception e) {
System.out.println("Warning: " + e.toString());
}
} catch (Exception e) {
throw new RuntimeException("(02310251044) Process start times : " + e.toString());
}
return result;
}
public static void main(String[] argv)
{
String sMax;
int iMax = 500;
if (argv.length > 0) {
sMax = argv[0];
try {
iMax = Integer.parseInt(sMax);
} catch (Exception e) {
System.out.println("Oops : " + e.toString());
System.exit(1);
}
}
for (int i = 0; i < iMax; ++i) {
System.out.print("\r" + i);
getStartTimes();
try {
Thread.sleep(1000);
} catch (Exception e) {
// do nothing
}
}
}
}
I was able to run it and RAMMAP didn't show more than a single winps.exe in the list (in fact, none most of the time).
This compared to the hundreds of winps.exe entries I've seen before, makes it likely that the tiny change of calling System.gc() resolved the issue.
My next step is to add the change to all relevant releases (2.9, 2.10, 2.11/Development) and to create new rpm packages.
I'll drop a note here as soon as I've completed the process.
Best regards,
Ronald