Skip to content

Commit 86dbda6

Browse files
authored
Merge pull request #867 from scouter-project/feature/866-exception-on-java17
Feature/866 exception on java17
2 parents b93d1de + 5f72471 commit 86dbda6

File tree

4 files changed

+171
-13
lines changed

4 files changed

+171
-13
lines changed

scouter.agent.java/src/main/java/scouter/agent/counter/jmx/LazyPlatformMBeanServer.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
package scouter.agent.counter.jmx;
22

3-
import scouter.agent.Logger;
4-
import scouter.agent.ObjTypeDetector;
5-
import scouter.util.StringIntMap;
6-
import scouter.util.SystemUtil;
7-
import scouter.util.ThreadUtil;
3+
import static scouter.lang.counters.CounterConstants.JBOSS;
4+
import static scouter.lang.counters.CounterConstants.WEBLOGIC;
5+
import static scouter.lang.counters.CounterConstants.WEBSPHERE;
86

9-
import javax.management.InstanceNotFoundException;
10-
import javax.management.MBeanServer;
11-
import javax.management.ObjectName;
127
import java.lang.management.ManagementFactory;
138
import java.lang.reflect.Field;
149
import java.lang.reflect.Method;
1510
import java.util.HashMap;
1611
import java.util.HashSet;
1712
import java.util.Map;
1813
import java.util.Set;
19-
20-
import static scouter.lang.counters.CounterConstants.*;
14+
import javax.management.InstanceNotFoundException;
15+
import javax.management.MBeanServer;
16+
import javax.management.ObjectName;
17+
import scouter.agent.JavaAgent;
18+
import scouter.agent.Logger;
19+
import scouter.agent.ObjTypeDetector;
20+
import scouter.agent.util.ModuleUtil;
21+
import scouter.util.StringIntMap;
22+
import scouter.util.SystemUtil;
23+
import scouter.util.ThreadUtil;
2124

2225
/**
2326
* refer to glowroot (https://github.com/glowroot/glowroot)
@@ -47,6 +50,15 @@ private LazyPlatformMBeanServer() {
4750

4851
public boolean checkInit() throws Exception {
4952
if (platformMBeanServer != null) return true;
53+
if (JavaAgent.isJava9plus()) {
54+
try {
55+
ModuleUtil.grantAccess(JavaAgent.getInstrumentation(),
56+
LazyPlatformMBeanServer.class.getName(),
57+
"sun.management.ManagementFactoryHelper");
58+
} catch (Throwable th) {
59+
Logger.println("MBEAN-01", th.getMessage(), th);
60+
}
61+
}
5062
if (waitForContainerToCreatePlatformMBeanServer) {
5163
String platformMBeanServerFieldName = SystemUtil.IS_JAVA_IBM ? "platformServer" : "platformMBeanServer";
5264
Field platformMBeanServerField =

scouter.agent.java/src/main/java/scouter/agent/proxy/ToolsMainFactory.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package scouter.agent.proxy;
1818

19+
import scouter.agent.JavaAgent;
20+
import scouter.agent.Logger;
21+
import scouter.agent.util.ModuleUtil;
1922
import scouter.lang.pack.MapPack;
2023
import scouter.lang.pack.Pack;
2124
import scouter.lang.value.ListValue;
@@ -27,6 +30,7 @@
2730

2831
public class ToolsMainFactory {
2932
private static final String TOOLS_MAIN = "scouter.xtra.tools.ToolsMain";
33+
private static boolean wasGrantedAccessToHSM = false;
3034

3135
public static MapPack heaphisto(Pack param) throws Throwable {
3236

@@ -50,6 +54,7 @@ public static MapPack heaphisto(Pack param) throws Throwable {
5054
try {
5155
Class c = Class.forName(TOOLS_MAIN, true, loader);
5256
IToolsMain toolsMain = (IToolsMain) c.newInstance();
57+
checkGrantAccess(loader);
5358
List<String> out = toolsMain.heaphisto(0, 100000, "all");
5459
ListValue lv = m.newList("heaphisto");
5560
for (int i = 0; i < out.size(); i++) {
@@ -76,6 +81,7 @@ public static void heaphisto(PrintWriter out) throws Throwable {
7681
try {
7782
Class c = Class.forName(TOOLS_MAIN, true, loader);
7883
IToolsMain toolsMain = (IToolsMain) c.newInstance();
84+
checkGrantAccess(loader);
7985
toolsMain.heaphisto(out);
8086
} catch (Exception e) {
8187
e.printStackTrace();
@@ -115,6 +121,7 @@ public static Pack threadDump(Pack param) throws Throwable {
115121
try {
116122
Class c = Class.forName(TOOLS_MAIN, true, loader);
117123
IToolsMain toolsMain = (IToolsMain) c.newInstance();
124+
checkGrantAccess(loader);
118125
List<String> out = (List<String>) toolsMain.threadDump(0, 100000);
119126
ListValue lv = m.newList("threadDump");
120127
for (int i = 0; i < out.size(); i++) {
@@ -143,9 +150,23 @@ public static synchronized void threadDump(PrintWriter out) throws Throwable {
143150
try {
144151
Class c = Class.forName(TOOLS_MAIN, true, loader);
145152
IToolsMain toolsMain = (IToolsMain) c.newInstance();
153+
checkGrantAccess(loader);
146154
toolsMain.threadDump(out);
147155
} catch (Exception e) {
148156
e.printStackTrace();
149157
}
150158
}
159+
160+
private static void checkGrantAccess(ClassLoader loader) {
161+
if (JavaAgent.isJava9plus() && !wasGrantedAccessToHSM) {
162+
try {
163+
ModuleUtil.grantAccess(JavaAgent.getInstrumentation(), TOOLS_MAIN, loader,
164+
"sun.tools.attach.HotSpotVirtualMachine", loader);
165+
} catch (Throwable th) {
166+
Logger.println("TOOLS-5", th.getMessage(), th);
167+
} finally {
168+
wasGrantedAccessToHSM = true;
169+
}
170+
}
171+
}
151172
}

scouter.agent.java/src/main/java/scouter/agent/trace/api/ForHttpURLConnection.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
* Copyright 2015 the original author or authors.
2+
* Copyright 2015 the original author or authors.
33
* @https://github.com/scouter-project/scouter
44
*
5-
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
77
* You may obtain a copy of the License at
88
*
@@ -12,14 +12,16 @@
1212
* distributed under the License is distributed on an "AS IS" BASIS,
1313
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
* See the License for the specific language governing permissions and
15-
* limitations under the License.
15+
* limitations under the License.
1616
*/
1717
package scouter.agent.trace.api;
1818

1919
import scouter.agent.Configure;
20+
import scouter.agent.JavaAgent;
2021
import scouter.agent.plugin.PluginHttpCallTrace;
2122
import scouter.agent.trace.HookArgs;
2223
import scouter.agent.trace.TraceContext;
24+
import scouter.agent.util.ModuleUtil;
2325
import scouter.lang.constants.B3Constant;
2426
import scouter.lang.step.ApiCallStep;
2527
import scouter.util.Hexa32;
@@ -36,6 +38,11 @@ public class ForHttpURLConnection implements ApiCallTraceHelper.IHelper {
3638

3739
static {
3840
try {
41+
if (JavaAgent.isJava9plus()) {
42+
ModuleUtil.grantAccess(JavaAgent.getInstrumentation(),
43+
ForHttpURLConnection.class.getName(),
44+
"sun.net.www.protocol.http.HttpURLConnection");
45+
}
3946
httpclass = sun.net.www.protocol.http.HttpURLConnection.class;
4047
inputStream = httpclass.getDeclaredField("inputStream");
4148
inputStream.setAccessible(true);
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
* @https://github.com/scouter-project/scouter
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package scouter.agent.util;
19+
20+
import java.lang.instrument.Instrumentation;
21+
import java.lang.reflect.Method;
22+
import java.util.HashMap;
23+
import java.util.HashSet;
24+
import java.util.Map;
25+
import java.util.Set;
26+
import scouter.agent.JavaAgent;
27+
import scouter.agent.Logger;
28+
29+
/**
30+
* refer to glowroot (https://github.com/glowroot/glowroot)
31+
*/
32+
public class ModuleUtil {
33+
34+
private static final ModuleUtil instance;
35+
36+
static {
37+
if (JavaAgent.isJava9plus()) {
38+
instance = new ModuleUtil();
39+
} else {
40+
instance = null;
41+
}
42+
}
43+
44+
private final Method getModuleMethod;
45+
private final Class<?> moduleClass;
46+
private final Method redefineModuleMethod;
47+
48+
private ModuleUtil() {
49+
try {
50+
getModuleMethod = Class.class.getMethod("getModule");
51+
moduleClass = Class.forName("java.lang.Module");
52+
redefineModuleMethod = Instrumentation.class.getMethod("redefineModule",
53+
moduleClass, Set.class, Map.class, Map.class, Set.class, Map.class);
54+
} catch (Exception e) {
55+
throw new IllegalStateException(e);
56+
}
57+
}
58+
59+
public static Object getModule(Class<?> clazz) throws Exception {
60+
return instance.getModuleInternal(clazz);
61+
}
62+
63+
public static void grantAccess(Instrumentation instrumentation, String fromClassName,
64+
String toClassName) throws Exception {
65+
instance.grantAccessInternal(instrumentation, fromClassName, null, toClassName, null);
66+
}
67+
68+
public static void grantAccess(Instrumentation instrumentation, String fromClassName,
69+
ClassLoader fromClassLoader,
70+
String toClassName, ClassLoader toClassLoader) throws Exception {
71+
instance.grantAccessInternal(instrumentation, fromClassName, fromClassLoader, toClassName,
72+
toClassLoader);
73+
}
74+
75+
private Object getModuleInternal(Class<?> clazz) throws Exception {
76+
// getModule() always returns non-null
77+
return getModuleMethod.invoke(clazz);
78+
}
79+
80+
private void grantAccessInternal(Instrumentation instrumentation, String fromClassName,
81+
ClassLoader fromClassLoader,
82+
String toClassName, ClassLoader toClassLoader) throws Exception {
83+
Class<?> fromClass;
84+
try {
85+
if (fromClassLoader == null) {
86+
fromClass = Class.forName(fromClassName);
87+
} else {
88+
fromClass = Class.forName(fromClassName, true, fromClassLoader);
89+
}
90+
} catch (ClassNotFoundException e) {
91+
Logger.println("MODULEUTIL-1", e.getMessage() + " : " + fromClassName, e);
92+
return;
93+
}
94+
Class<?> toClass;
95+
try {
96+
if (toClassLoader == null) {
97+
toClass = Class.forName(toClassName);
98+
} else {
99+
toClass = Class.forName(toClassName, true, toClassLoader);
100+
}
101+
} catch (ClassNotFoundException e) {
102+
Logger.println("MODULEUTIL-2", e.getMessage() + " : " + toClassName, e);
103+
return;
104+
}
105+
Map<String, Set<?>> extraOpens = new HashMap<>();
106+
Package pkg = toClass.getPackage();
107+
if (pkg != null) {
108+
Set openSet = new HashSet();
109+
openSet.add(getModuleMethod.invoke(fromClass));
110+
extraOpens.put(pkg.getName(), openSet);
111+
}
112+
// getModule() always returns non-null
113+
redefineModuleMethod.invoke(instrumentation, getModuleMethod.invoke(toClass),
114+
new HashSet<>(), new HashMap<>(), extraOpens, new HashSet<>(), new HashMap<>());
115+
Logger.println("extra opens module. from = " + fromClassName + " to = " + toClassName);
116+
}
117+
118+
}

0 commit comments

Comments
 (0)