Skip to content

Commit

Permalink
Merge pull request #867 from scouter-project/feature/866-exception-on…
Browse files Browse the repository at this point in the history
…-java17

Feature/866 exception on java17
  • Loading branch information
gunlee01 authored Aug 3, 2022
2 parents b93d1de + 5f72471 commit 86dbda6
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
package scouter.agent.counter.jmx;

import scouter.agent.Logger;
import scouter.agent.ObjTypeDetector;
import scouter.util.StringIntMap;
import scouter.util.SystemUtil;
import scouter.util.ThreadUtil;
import static scouter.lang.counters.CounterConstants.JBOSS;
import static scouter.lang.counters.CounterConstants.WEBLOGIC;
import static scouter.lang.counters.CounterConstants.WEBSPHERE;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static scouter.lang.counters.CounterConstants.*;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import scouter.agent.JavaAgent;
import scouter.agent.Logger;
import scouter.agent.ObjTypeDetector;
import scouter.agent.util.ModuleUtil;
import scouter.util.StringIntMap;
import scouter.util.SystemUtil;
import scouter.util.ThreadUtil;

/**
* refer to glowroot (https://github.com/glowroot/glowroot)
Expand Down Expand Up @@ -47,6 +50,15 @@ private LazyPlatformMBeanServer() {

public boolean checkInit() throws Exception {
if (platformMBeanServer != null) return true;
if (JavaAgent.isJava9plus()) {
try {
ModuleUtil.grantAccess(JavaAgent.getInstrumentation(),
LazyPlatformMBeanServer.class.getName(),
"sun.management.ManagementFactoryHelper");
} catch (Throwable th) {
Logger.println("MBEAN-01", th.getMessage(), th);
}
}
if (waitForContainerToCreatePlatformMBeanServer) {
String platformMBeanServerFieldName = SystemUtil.IS_JAVA_IBM ? "platformServer" : "platformMBeanServer";
Field platformMBeanServerField =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package scouter.agent.proxy;

import scouter.agent.JavaAgent;
import scouter.agent.Logger;
import scouter.agent.util.ModuleUtil;
import scouter.lang.pack.MapPack;
import scouter.lang.pack.Pack;
import scouter.lang.value.ListValue;
Expand All @@ -27,6 +30,7 @@

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

public static MapPack heaphisto(Pack param) throws Throwable {

Expand All @@ -50,6 +54,7 @@ public static MapPack heaphisto(Pack param) throws Throwable {
try {
Class c = Class.forName(TOOLS_MAIN, true, loader);
IToolsMain toolsMain = (IToolsMain) c.newInstance();
checkGrantAccess(loader);
List<String> out = toolsMain.heaphisto(0, 100000, "all");
ListValue lv = m.newList("heaphisto");
for (int i = 0; i < out.size(); i++) {
Expand All @@ -76,6 +81,7 @@ public static void heaphisto(PrintWriter out) throws Throwable {
try {
Class c = Class.forName(TOOLS_MAIN, true, loader);
IToolsMain toolsMain = (IToolsMain) c.newInstance();
checkGrantAccess(loader);
toolsMain.heaphisto(out);
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -115,6 +121,7 @@ public static Pack threadDump(Pack param) throws Throwable {
try {
Class c = Class.forName(TOOLS_MAIN, true, loader);
IToolsMain toolsMain = (IToolsMain) c.newInstance();
checkGrantAccess(loader);
List<String> out = (List<String>) toolsMain.threadDump(0, 100000);
ListValue lv = m.newList("threadDump");
for (int i = 0; i < out.size(); i++) {
Expand Down Expand Up @@ -143,9 +150,23 @@ public static synchronized void threadDump(PrintWriter out) throws Throwable {
try {
Class c = Class.forName(TOOLS_MAIN, true, loader);
IToolsMain toolsMain = (IToolsMain) c.newInstance();
checkGrantAccess(loader);
toolsMain.threadDump(out);
} catch (Exception e) {
e.printStackTrace();
}
}

private static void checkGrantAccess(ClassLoader loader) {
if (JavaAgent.isJava9plus() && !wasGrantedAccessToHSM) {
try {
ModuleUtil.grantAccess(JavaAgent.getInstrumentation(), TOOLS_MAIN, loader,
"sun.tools.attach.HotSpotVirtualMachine", loader);
} catch (Throwable th) {
Logger.println("TOOLS-5", th.getMessage(), th);
} finally {
wasGrantedAccessToHSM = true;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
Expand All @@ -12,14 +12,16 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
package scouter.agent.trace.api;

import scouter.agent.Configure;
import scouter.agent.JavaAgent;
import scouter.agent.plugin.PluginHttpCallTrace;
import scouter.agent.trace.HookArgs;
import scouter.agent.trace.TraceContext;
import scouter.agent.util.ModuleUtil;
import scouter.lang.constants.B3Constant;
import scouter.lang.step.ApiCallStep;
import scouter.util.Hexa32;
Expand All @@ -36,6 +38,11 @@ public class ForHttpURLConnection implements ApiCallTraceHelper.IHelper {

static {
try {
if (JavaAgent.isJava9plus()) {
ModuleUtil.grantAccess(JavaAgent.getInstrumentation(),
ForHttpURLConnection.class.getName(),
"sun.net.www.protocol.http.HttpURLConnection");
}
httpclass = sun.net.www.protocol.http.HttpURLConnection.class;
inputStream = httpclass.getDeclaredField("inputStream");
inputStream.setAccessible(true);
Expand Down
118 changes: 118 additions & 0 deletions scouter.agent.java/src/main/java/scouter/agent/util/ModuleUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package scouter.agent.util;

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import scouter.agent.JavaAgent;
import scouter.agent.Logger;

/**
* refer to glowroot (https://github.com/glowroot/glowroot)
*/
public class ModuleUtil {

private static final ModuleUtil instance;

static {
if (JavaAgent.isJava9plus()) {
instance = new ModuleUtil();
} else {
instance = null;
}
}

private final Method getModuleMethod;
private final Class<?> moduleClass;
private final Method redefineModuleMethod;

private ModuleUtil() {
try {
getModuleMethod = Class.class.getMethod("getModule");
moduleClass = Class.forName("java.lang.Module");
redefineModuleMethod = Instrumentation.class.getMethod("redefineModule",
moduleClass, Set.class, Map.class, Map.class, Set.class, Map.class);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

public static Object getModule(Class<?> clazz) throws Exception {
return instance.getModuleInternal(clazz);
}

public static void grantAccess(Instrumentation instrumentation, String fromClassName,
String toClassName) throws Exception {
instance.grantAccessInternal(instrumentation, fromClassName, null, toClassName, null);
}

public static void grantAccess(Instrumentation instrumentation, String fromClassName,
ClassLoader fromClassLoader,
String toClassName, ClassLoader toClassLoader) throws Exception {
instance.grantAccessInternal(instrumentation, fromClassName, fromClassLoader, toClassName,
toClassLoader);
}

private Object getModuleInternal(Class<?> clazz) throws Exception {
// getModule() always returns non-null
return getModuleMethod.invoke(clazz);
}

private void grantAccessInternal(Instrumentation instrumentation, String fromClassName,
ClassLoader fromClassLoader,
String toClassName, ClassLoader toClassLoader) throws Exception {
Class<?> fromClass;
try {
if (fromClassLoader == null) {
fromClass = Class.forName(fromClassName);
} else {
fromClass = Class.forName(fromClassName, true, fromClassLoader);
}
} catch (ClassNotFoundException e) {
Logger.println("MODULEUTIL-1", e.getMessage() + " : " + fromClassName, e);
return;
}
Class<?> toClass;
try {
if (toClassLoader == null) {
toClass = Class.forName(toClassName);
} else {
toClass = Class.forName(toClassName, true, toClassLoader);
}
} catch (ClassNotFoundException e) {
Logger.println("MODULEUTIL-2", e.getMessage() + " : " + toClassName, e);
return;
}
Map<String, Set<?>> extraOpens = new HashMap<>();
Package pkg = toClass.getPackage();
if (pkg != null) {
Set openSet = new HashSet();
openSet.add(getModuleMethod.invoke(fromClass));
extraOpens.put(pkg.getName(), openSet);
}
// getModule() always returns non-null
redefineModuleMethod.invoke(instrumentation, getModuleMethod.invoke(toClass),
new HashSet<>(), new HashMap<>(), extraOpens, new HashSet<>(), new HashMap<>());
Logger.println("extra opens module. from = " + fromClassName + " to = " + toClassName);
}

}

0 comments on commit 86dbda6

Please sign in to comment.