Skip to content

Commit 6a36128

Browse files
committed
Native (java) process memory leak, closes elastic#1118.
1 parent eb8ebbd commit 6a36128

File tree

4 files changed

+117
-24
lines changed

4 files changed

+117
-24
lines changed

modules/elasticsearch/src/main/java/org/elasticsearch/monitor/jvm/JvmMonitorService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ public class JvmMonitorService extends AbstractLifecycleComponent<JvmMonitorServ
6161
this.threadPool = threadPool;
6262
this.dumpMonitorService = dumpMonitorService;
6363

64-
this.enabled = componentSettings.getAsBoolean("enabled", true);
64+
this.enabled = componentSettings.getAsBoolean("enabled", JvmStats.isLastGcEnabled());
6565
this.interval = componentSettings.getAsTime("interval", timeValueSeconds(1));
6666
this.gcThreshold = componentSettings.getAsTime("gc_threshold", timeValueMillis(5000));
67+
68+
logger.debug("enabled [{}], last_gc_enabled [{}], interval [{}], gc_threshold [{}]", enabled, JvmStats.isLastGcEnabled(), interval, gcThreshold);
6769
}
6870

6971
@Override protected void doStart() throws ElasticSearchException {

modules/elasticsearch/src/main/java/org/elasticsearch/monitor/jvm/JvmStats.java

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.monitor.jvm;
2121

22+
import org.elasticsearch.common.Booleans;
2223
import org.elasticsearch.common.collect.Iterators;
2324
import org.elasticsearch.common.io.stream.StreamInput;
2425
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -42,11 +43,16 @@
4243
*/
4344
public class JvmStats implements Streamable, Serializable, ToXContent {
4445

46+
private static boolean enableLastGc;
47+
48+
public static boolean isLastGcEnabled() {
49+
return enableLastGc;
50+
}
51+
4552
private final static RuntimeMXBean runtimeMXBean;
4653
private final static MemoryMXBean memoryMXBean;
4754
private final static ThreadMXBean threadMXBean;
4855

49-
private static boolean sunGc;
5056
private static Method getLastGcInfoMethod;
5157
private static Method getMemoryUsageBeforeGcMethod;
5258
private static Method getMemoryUsageAfterGcMethod;
@@ -59,28 +65,32 @@ public class JvmStats implements Streamable, Serializable, ToXContent {
5965
memoryMXBean = ManagementFactory.getMemoryMXBean();
6066
threadMXBean = ManagementFactory.getThreadMXBean();
6167

62-
try {
63-
Class sunGcClass = Class.forName("com.sun.management.GarbageCollectorMXBean");
64-
Class gcInfoClass = Class.forName("com.sun.management.GcInfo");
65-
66-
getLastGcInfoMethod = sunGcClass.getDeclaredMethod("getLastGcInfo");
67-
getLastGcInfoMethod.setAccessible(true);
68-
69-
getMemoryUsageBeforeGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageBeforeGc");
70-
getMemoryUsageBeforeGcMethod.setAccessible(true);
71-
getMemoryUsageAfterGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageAfterGc");
72-
getMemoryUsageAfterGcMethod.setAccessible(true);
73-
getStartTimeMethod = gcInfoClass.getDeclaredMethod("getStartTime");
74-
getStartTimeMethod.setAccessible(true);
75-
getEndTimeMethod = gcInfoClass.getDeclaredMethod("getEndTime");
76-
getEndTimeMethod.setAccessible(true);
77-
getDurationMethod = gcInfoClass.getDeclaredMethod("getDuration");
78-
getDurationMethod.setAccessible(true);
79-
80-
sunGc = true;
81-
} catch (Throwable ex) {
82-
sunGc = false;
68+
boolean enableLastGc = Booleans.parseBoolean(System.getProperty("monitory.jvm.enable_last_gc"), false);
69+
if (enableLastGc) {
70+
try {
71+
Class sunGcClass = Class.forName("com.sun.management.GarbageCollectorMXBean");
72+
Class gcInfoClass = Class.forName("com.sun.management.GcInfo");
73+
74+
getLastGcInfoMethod = sunGcClass.getDeclaredMethod("getLastGcInfo");
75+
getLastGcInfoMethod.setAccessible(true);
76+
77+
getMemoryUsageBeforeGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageBeforeGc");
78+
getMemoryUsageBeforeGcMethod.setAccessible(true);
79+
getMemoryUsageAfterGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageAfterGc");
80+
getMemoryUsageAfterGcMethod.setAccessible(true);
81+
getStartTimeMethod = gcInfoClass.getDeclaredMethod("getStartTime");
82+
getStartTimeMethod.setAccessible(true);
83+
getEndTimeMethod = gcInfoClass.getDeclaredMethod("getEndTime");
84+
getEndTimeMethod.setAccessible(true);
85+
getDurationMethod = gcInfoClass.getDeclaredMethod("getDuration");
86+
getDurationMethod.setAccessible(true);
87+
88+
} catch (Throwable ex) {
89+
enableLastGc = false;
90+
}
8391
}
92+
93+
JvmStats.enableLastGc = false;
8494
}
8595

8696
public static JvmStats jvmStats() {
@@ -106,7 +116,7 @@ public static JvmStats jvmStats() {
106116
stats.gc.collectors[i].name = gcMxBean.getName();
107117
stats.gc.collectors[i].collectionCount = gcMxBean.getCollectionCount();
108118
stats.gc.collectors[i].collectionTime = gcMxBean.getCollectionTime();
109-
if (sunGc) {
119+
if (enableLastGc) {
110120
try {
111121
Object lastGcInfo = getLastGcInfoMethod.invoke(gcMxBean);
112122
if (lastGcInfo != null) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to Elastic Search and Shay Banon under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. Elastic Search licenses this
6+
* file to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.test.stress.leaks;
21+
22+
import org.elasticsearch.monitor.jvm.JvmService;
23+
import org.elasticsearch.monitor.network.NetworkService;
24+
import org.elasticsearch.monitor.os.OsService;
25+
import org.elasticsearch.monitor.process.ProcessService;
26+
import org.elasticsearch.node.NodeBuilder;
27+
import org.elasticsearch.node.internal.InternalNode;
28+
29+
public class GenericStatsLeak {
30+
31+
public static void main(String[] args) {
32+
InternalNode node = (InternalNode) NodeBuilder.nodeBuilder().node();
33+
34+
JvmService jvmService = node.injector().getInstance(JvmService.class);
35+
OsService osService = node.injector().getInstance(OsService.class);
36+
ProcessService processService = node.injector().getInstance(ProcessService.class);
37+
NetworkService networkService = node.injector().getInstance(NetworkService.class);
38+
39+
while (true) {
40+
jvmService.stats();
41+
osService.stats();
42+
processService.stats();
43+
networkService.stats();
44+
}
45+
}
46+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Licensed to Elastic Search and Shay Banon under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. Elastic Search licenses this
6+
* file to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.test.stress.leaks;
21+
22+
import org.elasticsearch.monitor.jvm.JvmStats;
23+
24+
/**
25+
* This test mainly comes to check the native memory leak with getLastGCInfo (which is now
26+
* disabled by default).
27+
*/
28+
public class JvmStatsLeak {
29+
30+
public static void main(String[] args) {
31+
while (true) {
32+
JvmStats.jvmStats();
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)