Skip to content

Commit ce8d435

Browse files
committed
GH-187 try to detect tunneled JMX application
1 parent b0a5476 commit ce8d435

File tree

5 files changed

+71
-4
lines changed

5 files changed

+71
-4
lines changed

visualvm/application/manifest.mf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ OpenIDE-Module: org.graalvm.visualvm.application/2
55
OpenIDE-Module-Layer: org/graalvm/visualvm/application/resources/layer.xml
66
OpenIDE-Module-Install: org/graalvm/visualvm/application/Installer.class
77
OpenIDE-Module-Localizing-Bundle: org/graalvm/visualvm/application/resources/Bundle.properties
8-
OpenIDE-Module-Specification-Version: 2.3
8+
OpenIDE-Module-Specification-Version: 2.4
99

visualvm/application/src/org/graalvm/visualvm/application/Application.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public final Host getHost() {
117117
*
118118
* @return true if the application is running on Host.LOCALHOST, false otherwise.
119119
*/
120-
public final boolean isLocalApplication() {
120+
public boolean isLocalApplication() {
121121
return Host.LOCALHOST.equals(getHost());
122122
}
123123

visualvm/jmx/nbproject/project.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<compile-dependency/>
1313
<run-dependency>
1414
<release-version>2</release-version>
15-
<specification-version>2.0</specification-version>
15+
<specification-version>2.4</specification-version>
1616
</run-dependency>
1717
</dependency>
1818
<dependency>

visualvm/jmx/src/org/graalvm/visualvm/jmx/impl/JmxApplication.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.beans.PropertyChangeEvent;
2929
import java.beans.PropertyChangeListener;
3030
import java.io.IOException;
31+
import java.lang.management.ManagementFactory;
3132
import org.graalvm.visualvm.application.Application;
3233
import org.graalvm.visualvm.application.jvm.Jvm;
3334
import org.graalvm.visualvm.core.datasource.Storage;
@@ -41,6 +42,8 @@
4142
import org.graalvm.visualvm.tools.jmx.JvmMXBeans;
4243
import org.graalvm.visualvm.tools.jmx.JvmMXBeansFactory;
4344
import java.lang.management.RuntimeMXBean;
45+
import java.util.Map;
46+
import java.util.Objects;
4447
import java.util.logging.Level;
4548
import java.util.logging.Logger;
4649
import javax.management.remote.JMXServiceURL;
@@ -110,6 +113,37 @@ public int getPid() {
110113
return pid;
111114
}
112115

116+
private static final String[] HOST_PROPS = {
117+
"os.arch",
118+
"os.name",
119+
"os.version",
120+
"user.home",
121+
"user.name"
122+
};
123+
public boolean isLocalApplication() {
124+
if (super.isLocalApplication()) {
125+
// try to detect tunneled application
126+
if (getState() == Stateful.STATE_AVAILABLE) {
127+
if (jmxModel != null && jmxModel.getConnectionState() == ConnectionState.CONNECTED) {
128+
JvmMXBeans mxbeans = JvmMXBeansFactory.getJvmMXBeans(jmxModel);
129+
if (mxbeans != null) {
130+
RuntimeMXBean rt = mxbeans.getRuntimeMXBean();
131+
if (rt != null) {
132+
Map<String, String> appProperties = rt.getSystemProperties();
133+
if (!matchProps(HOST_PROPS, appProperties)) {
134+
return false;
135+
}
136+
if (!checkHostName(ManagementFactory.getRuntimeMXBean(), rt)) {
137+
return false;
138+
}
139+
}
140+
}
141+
}
142+
}
143+
return true;
144+
}
145+
return false;
146+
}
113147

114148
public boolean supportsUserRemove() {
115149
return true;
@@ -247,5 +281,32 @@ final boolean isHeartbeatDisabled() {
247281
static boolean supportsHeartbeat(JmxApplication app) {
248282
return !app.isRemoved() && !app.isHeartbeatDisabled();
249283
}
284+
285+
private boolean matchProps(String[] propNames, Map<String, String> appProperties) {
286+
for (String prop : propNames) {
287+
String localProp = System.getProperty(prop);
288+
String appProp = appProperties.get(prop);
289+
if (!Objects.equals(localProp, appProp)) {
290+
return false;
291+
}
292+
}
293+
return true;
294+
}
295+
296+
private boolean checkHostName(RuntimeMXBean localRuntime, RuntimeMXBean remoteRuntime) {
297+
String localHost = getHostName(localRuntime.getName());
298+
String remoteHost = getHostName(remoteRuntime.getName());
299+
300+
return Objects.equals(localHost, remoteHost);
301+
}
250302

303+
private String getHostName(String runtimeName) {
304+
if (runtimeName == null) return null;
305+
int index = runtimeName.indexOf("@"); // NOI18N
306+
307+
if (index >= 0) {
308+
return runtimeName.substring(index+1);
309+
}
310+
return null;
311+
}
251312
}

visualvm/jvmstat/src/org/graalvm/visualvm/jvmstat/application/JvmstatApplicationProvider.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,14 @@ public MonitoredHost getMonitoredHost(Application app) {
382382
return getLocalMonitoredHost();
383383
}
384384
if (!(app instanceof JvmstatApplication)) {
385-
String appId = createId(app.getHost(),app.getPid());
385+
Host host = app.getHost();
386+
String appId = createId(host, app.getPid());
387+
386388
japp = applications.get(appId);
389+
if (japp!=null && !host.equals(japp.getHost())) {
390+
// app is application running on different host via e.g. ssh tunnel
391+
japp = null;
392+
}
387393
} else {
388394
japp = (JvmstatApplication) app;
389395
}

0 commit comments

Comments
 (0)