Skip to content

Commit 8551294

Browse files
committed
8230857: Avoid reflection in sun.tools.common.ProcessHelper
Reviewed-by: sspitsyn, dholmes
1 parent f92526e commit 8551294

File tree

4 files changed

+55
-70
lines changed

4 files changed

+55
-70
lines changed

src/jdk.jcmd/linux/classes/sun/tools/ProcessHelper.java renamed to src/jdk.jcmd/linux/classes/sun/tools/common/ProcessHelper.java

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,21 @@
2323
* questions.
2424
*/
2525

26-
package sun.tools;
26+
package sun.tools.common;
2727

2828
import java.io.IOException;
2929
import java.io.UncheckedIOException;
3030
import java.nio.file.Files;
3131
import java.nio.file.Paths;
32-
import java.util.jar.Attributes;
33-
import java.util.jar.JarFile;
3432
import java.util.stream.Stream;
3533

3634
/**
3735
* A helper class that retrieves the main class name for
3836
* a running Java process using the proc filesystem (procfs)
3937
*/
40-
public class ProcessHelper implements sun.tools.common.ProcessHelper {
41-
38+
final class ProcessHelper {
4239

4340
private static final String CMD_PREFIX = "cmd:";
44-
private static final ProcessHelper INSTANCE = new ProcessHelper();
45-
46-
public static ProcessHelper getInstance() {
47-
return INSTANCE;
48-
}
4941

5042
/**
5143
* Gets the main class name for the given Java process by parsing the
@@ -57,8 +49,7 @@ public static ProcessHelper getInstance() {
5749
* @return the main class name or null if the process no longer exists or
5850
* was started with a native launcher (e.g. jcmd etc)
5951
*/
60-
61-
public String getMainClass(String pid) {
52+
static String getMainClass(String pid) {
6253
String cmdLine = getCommandLine(pid);
6354
if (cmdLine == null) {
6455
return null;
@@ -69,7 +60,7 @@ public String getMainClass(String pid) {
6960
String[] parts = cmdLine.split("\0");
7061
String mainClass = null;
7162

72-
if(parts.length == 0) {
63+
if (parts.length == 0) {
7364
return null;
7465
}
7566

@@ -120,7 +111,6 @@ public String getMainClass(String pid) {
120111
mainClass = parts[i];
121112
}
122113
return mainClass;
123-
124114
}
125115

126116
private static String getCommandLine(String pid) {
@@ -134,16 +124,13 @@ private static String getCommandLine(String pid) {
134124

135125
private static boolean isModuleWhiteSpaceOption(String option) {
136126
return option.equals("-p") ||
137-
option.equals("--module-path") ||
138-
option.equals("--upgrade-module-path") ||
139-
option.equals("--add-modules") ||
140-
option.equals("--limit-modules") ||
141-
option.equals("--add-exports") ||
142-
option.equals("--add-opens") ||
143-
option.equals("--add-reads") ||
144-
option.equals("--patch-module");
127+
option.equals("--module-path") ||
128+
option.equals("--upgrade-module-path") ||
129+
option.equals("--add-modules") ||
130+
option.equals("--limit-modules") ||
131+
option.equals("--add-exports") ||
132+
option.equals("--add-opens") ||
133+
option.equals("--add-reads") ||
134+
option.equals("--patch-module");
145135
}
146-
147136
}
148-
149-

src/jdk.jcmd/share/classes/sun/tools/common/ProcessArgumentMatcher.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,10 @@ private static String getExcludeStringFrom(Class<?> excludeClass) {
7979

8080
private static boolean check(VirtualMachineDescriptor vmd, String excludeClass, String partialMatch) {
8181

82-
String mainClass = null;
82+
// Try to get the main class name using (platform specific) ProcessHelper
83+
String mainClass = ProcessHelper.getMainClass(vmd.id());
8384

84-
// Get the main class name using platform specific helper
85-
ProcessHelper helper = ProcessHelper.platformProcessHelper();
86-
if (helper != null) {
87-
mainClass = helper.getMainClass(vmd.id());
88-
}
89-
90-
// If the main class name is still unset then retrieve it with the attach mechanism
85+
// If the main class name could not be retrieved by ProcessHelper, get it with the attach mechanism
9186
if (mainClass == null) {
9287
try {
9388
VmIdentifier vmId = new VmIdentifier(vmd.id());

src/jdk.jcmd/share/classes/sun/tools/common/ProcessHelper.java

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,20 @@
2525

2626
package sun.tools.common;
2727

28-
import java.lang.reflect.Method;
29-
3028
/**
3129
* A helper class to retrieve the main class name for a running
32-
* Java process.
30+
* Java process. Default implementation returns null. Platform specific
31+
* implementation currently available for Linux only.
3332
*/
34-
35-
public interface ProcessHelper {
36-
37-
/**
38-
* Returns an instance of the ProcessHelper class.
39-
*
40-
* @return ProcessHelper object or null if not supported on this platform.
41-
*/
42-
public static ProcessHelper platformProcessHelper() {
43-
try {
44-
Class<?> c = Class.forName("sun.tools.ProcessHelper");
45-
@SuppressWarnings("unchecked")
46-
Method m = c.getMethod("getInstance");
47-
return (ProcessHelper) m.invoke(null);
48-
} catch (ClassNotFoundException e) {
49-
return null;
50-
} catch (ReflectiveOperationException e) {
51-
throw new InternalError(e);
52-
}
53-
}
54-
33+
final class ProcessHelper {
5534

5635
/**
5736
* Returns the main class name for the given Java process
5837
*
5938
* @param pid - process ID (pid)
6039
* @return main class name or null if the main class could not be retrieved
6140
*/
62-
63-
String getMainClass(String pid);
41+
static String getMainClass(String pid) {
42+
return null;
43+
}
6444
}

test/jdk/sun/tools/jcmd/TestProcessHelper.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,13 @@
2121
* questions.
2222
*/
2323

24-
import jdk.internal.module.ModuleInfoWriter;
25-
import jdk.test.lib.JDKToolFinder;
26-
import jdk.test.lib.process.ProcessTools;
27-
import jdk.test.lib.util.JarUtils;
28-
import sun.tools.common.ProcessHelper;
29-
3024
import java.io.File;
3125
import java.io.IOException;
3226
import java.io.OutputStream;
27+
import java.lang.invoke.MethodHandle;
28+
import java.lang.invoke.MethodHandles;
3329
import java.lang.module.ModuleDescriptor;
30+
import java.lang.reflect.Method;
3431
import java.nio.file.FileSystems;
3532
import java.nio.file.Files;
3633
import java.nio.file.Path;
@@ -44,6 +41,11 @@
4441
import java.util.stream.Collectors;
4542
import java.util.stream.Stream;
4643

44+
import jdk.internal.module.ModuleInfoWriter;
45+
import jdk.test.lib.JDKToolFinder;
46+
import jdk.test.lib.process.ProcessTools;
47+
import jdk.test.lib.util.JarUtils;
48+
4749
/*
4850
* @test
4951
* @bug 8205654
@@ -52,15 +54,13 @@
5254
*
5355
* @requires os.family == "linux"
5456
* @library /test/lib
55-
* @modules jdk.jcmd/sun.tools.common
57+
* @modules jdk.jcmd/sun.tools.common:+open
5658
* java.base/jdk.internal.module
5759
* @build test.TestProcess
5860
* @run main/othervm TestProcessHelper
5961
*/
6062
public class TestProcessHelper {
6163

62-
private ProcessHelper PROCESS_HELPER = ProcessHelper.platformProcessHelper();
63-
6464
private static final String TEST_PROCESS_MAIN_CLASS_NAME = "TestProcess";
6565
private static final String TEST_PROCESS_MAIN_CLASS_PACKAGE = "test";
6666
private static final String TEST_PROCESS_MAIN_CLASS = TEST_PROCESS_MAIN_CLASS_PACKAGE + "."
@@ -89,6 +89,29 @@ public class TestProcessHelper {
8989

9090
private static final String[] PATCH_MODULE_OPTIONS = {"--patch-module", null};
9191

92+
private static final MethodHandle MH_GET_MAIN_CLASS = resolveMainClassMH();
93+
94+
private static MethodHandle resolveMainClassMH() {
95+
try {
96+
Method getMainClassMethod = Class
97+
.forName("sun.tools.common.ProcessHelper")
98+
.getDeclaredMethod("getMainClass", String.class);
99+
getMainClassMethod.setAccessible(true);
100+
return MethodHandles.lookup().unreflect(getMainClassMethod);
101+
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException e) {
102+
throw new RuntimeException(e);
103+
}
104+
}
105+
106+
private static String callGetMainClass(Process p) {
107+
try {
108+
return (String)MH_GET_MAIN_CLASS.invoke(Long.toString(p.pid()));
109+
} catch (Throwable e) {
110+
throw new RuntimeException(e);
111+
}
112+
113+
}
114+
92115
public static void main(String[] args) throws Exception {
93116
new TestProcessHelper().runTests();
94117
}
@@ -188,7 +211,7 @@ private void testModule() throws Exception {
188211
}
189212

190213
private void checkMainClass(Process p, String expectedMainClass) {
191-
String mainClass = PROCESS_HELPER.getMainClass(Long.toString(p.pid()));
214+
String mainClass = callGetMainClass(p);
192215
// getMainClass() may return null, e.g. due to timing issues.
193216
// Attempt some limited retries.
194217
if (mainClass == null) {
@@ -204,7 +227,7 @@ private void checkMainClass(Process p, String expectedMainClass) {
204227
} catch (InterruptedException e) {
205228
// ignore
206229
}
207-
mainClass = PROCESS_HELPER.getMainClass(Long.toString(p.pid()));
230+
mainClass = callGetMainClass(p);
208231
retrycount++;
209232
sleepms *= 2;
210233
}

0 commit comments

Comments
 (0)