Skip to content

Commit

Permalink
Only call getRuntimeMXBean if needed (#605)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukehutch committed Nov 26, 2021
1 parent 7a66f12 commit c946fa9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 29 deletions.
1 change: 1 addition & 0 deletions src/main/java/io/github/classgraph/ClassGraph.java
Expand Up @@ -1764,6 +1764,7 @@ public List<ModuleRef> getModules() {
* @return The {@link ModulePathInfo}.
*/
public ModulePathInfo getModulePathInfo() {
scanSpec.modulePathInfo.getRuntimeInfo();
return scanSpec.modulePathInfo;
}
}
66 changes: 37 additions & 29 deletions src/main/java/io/github/classgraph/ModulePathInfo.java
Expand Up @@ -33,6 +33,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import nonapi.io.github.classgraph.reflection.ReflectionUtils;
import nonapi.io.github.classgraph.utils.JarUtils;
Expand Down Expand Up @@ -126,36 +127,43 @@ public class ModulePathInfo {
'\0' // --add-reads (only one param per switch)
);

/** Set to true once {@link #getRuntimeInfo()} is called. */
private final AtomicBoolean gotRuntimeInfo = new AtomicBoolean();

/** Construct a {@link ModulePathInfo}. */
public ModulePathInfo() {
// Read the raw commandline arguments to get the module path override parameters.
// If the java.management module is not present in the deployed runtime (for JDK 9+), or the runtime
// does not contain the java.lang.management package (e.g. the Android build system, which also does
// not support JPMS currently), then skip trying to read the commandline arguments (#404).
final Class<?> managementFactory = ReflectionUtils
.classForNameOrNull("java.lang.management.ManagementFactory");
final Object runtimeMXBean = managementFactory == null ? null
: ReflectionUtils.invokeStaticMethod(/* throwException = */ false, managementFactory,
"getRuntimeMXBean");
@SuppressWarnings("unchecked")
final List<String> commandlineArguments = runtimeMXBean == null ? null
: (List<String>) ReflectionUtils.invokeMethod(/* throwException = */ false, runtimeMXBean,
"getInputArguments");
if (commandlineArguments != null) {
for (final String arg : commandlineArguments) {
for (int i = 0; i < fields.size(); i++) {
final String argSwitch = argSwitches.get(i);
if (arg.startsWith(argSwitch)) {
final String argParam = arg.substring(argSwitch.length());
final Set<String> argField = fields.get(i);
final char sepChar = argPartSeparatorChars.get(i);
if (sepChar == '\0') {
// Only one param per switch
argField.add(argParam);
} else {
// Split arg param into parts
argField.addAll(Arrays
.asList(JarUtils.smartPathSplit(argParam, sepChar, /* scanSpec = */ null)));
void getRuntimeInfo() {
// Only call this reflective method if ModulePathInfo is specifically requested, to avoid illegal
// access warning on some JREs, e.g. Adopt JDK 11 (#605)
if (!gotRuntimeInfo.getAndSet(true)) {
// Read the raw commandline arguments to get the module path override parameters.
// If the java.management module is not present in the deployed runtime (for JDK 9+), or the runtime
// does not contain the java.lang.management package (e.g. the Android build system, which also does
// not support JPMS currently), then skip trying to read the commandline arguments (#404).
final Class<?> managementFactory = ReflectionUtils
.classForNameOrNull("java.lang.management.ManagementFactory");
final Object runtimeMXBean = managementFactory == null ? null
: ReflectionUtils.invokeStaticMethod(/* throwException = */ false, managementFactory,
"getRuntimeMXBean");
@SuppressWarnings("unchecked")
final List<String> commandlineArguments = runtimeMXBean == null ? null
: (List<String>) ReflectionUtils.invokeMethod(/* throwException = */ false, runtimeMXBean,
"getInputArguments");
if (commandlineArguments != null) {
for (final String arg : commandlineArguments) {
for (int i = 0; i < fields.size(); i++) {
final String argSwitch = argSwitches.get(i);
if (arg.startsWith(argSwitch)) {
final String argParam = arg.substring(argSwitch.length());
final Set<String> argField = fields.get(i);
final char sepChar = argPartSeparatorChars.get(i);
if (sepChar == '\0') {
// Only one param per switch
argField.add(argParam);
} else {
// Split arg param into parts
argField.addAll(Arrays
.asList(JarUtils.smartPathSplit(argParam, sepChar, /* scanSpec = */ null)));
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/io/github/classgraph/ScanResult.java
Expand Up @@ -449,6 +449,7 @@ public List<ModuleRef> getModules() {
* @return The {@link ModulePathInfo}.
*/
public ModulePathInfo getModulePathInfo() {
scanSpec.modulePathInfo.getRuntimeInfo();
return scanSpec.modulePathInfo;
}

Expand Down

0 comments on commit c946fa9

Please sign in to comment.