Native (java) process memory leak, closes #1118.
This commit is contained in:
parent
fdbcec8a84
commit
1033249f0c
|
@ -61,9 +61,11 @@ public class JvmMonitorService extends AbstractLifecycleComponent<JvmMonitorServ
|
||||||
this.threadPool = threadPool;
|
this.threadPool = threadPool;
|
||||||
this.dumpMonitorService = dumpMonitorService;
|
this.dumpMonitorService = dumpMonitorService;
|
||||||
|
|
||||||
this.enabled = componentSettings.getAsBoolean("enabled", true);
|
this.enabled = componentSettings.getAsBoolean("enabled", JvmStats.isLastGcEnabled());
|
||||||
this.interval = componentSettings.getAsTime("interval", timeValueSeconds(1));
|
this.interval = componentSettings.getAsTime("interval", timeValueSeconds(1));
|
||||||
this.gcThreshold = componentSettings.getAsTime("gc_threshold", timeValueMillis(5000));
|
this.gcThreshold = componentSettings.getAsTime("gc_threshold", timeValueMillis(5000));
|
||||||
|
|
||||||
|
logger.debug("enabled [{}], last_gc_enabled [{}], interval [{}], gc_threshold [{}]", enabled, JvmStats.isLastGcEnabled(), interval, gcThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void doStart() throws ElasticSearchException {
|
@Override protected void doStart() throws ElasticSearchException {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.monitor.jvm;
|
package org.elasticsearch.monitor.jvm;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.Booleans;
|
||||||
import org.elasticsearch.common.collect.Iterators;
|
import org.elasticsearch.common.collect.Iterators;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
@ -47,11 +48,16 @@ import java.util.concurrent.TimeUnit;
|
||||||
*/
|
*/
|
||||||
public class JvmStats implements Streamable, Serializable, ToXContent {
|
public class JvmStats implements Streamable, Serializable, ToXContent {
|
||||||
|
|
||||||
|
private static boolean enableLastGc;
|
||||||
|
|
||||||
|
public static boolean isLastGcEnabled() {
|
||||||
|
return enableLastGc;
|
||||||
|
}
|
||||||
|
|
||||||
private final static RuntimeMXBean runtimeMXBean;
|
private final static RuntimeMXBean runtimeMXBean;
|
||||||
private final static MemoryMXBean memoryMXBean;
|
private final static MemoryMXBean memoryMXBean;
|
||||||
private final static ThreadMXBean threadMXBean;
|
private final static ThreadMXBean threadMXBean;
|
||||||
|
|
||||||
private static boolean sunGc;
|
|
||||||
private static Method getLastGcInfoMethod;
|
private static Method getLastGcInfoMethod;
|
||||||
private static Method getMemoryUsageBeforeGcMethod;
|
private static Method getMemoryUsageBeforeGcMethod;
|
||||||
private static Method getMemoryUsageAfterGcMethod;
|
private static Method getMemoryUsageAfterGcMethod;
|
||||||
|
@ -64,28 +70,32 @@ public class JvmStats implements Streamable, Serializable, ToXContent {
|
||||||
memoryMXBean = ManagementFactory.getMemoryMXBean();
|
memoryMXBean = ManagementFactory.getMemoryMXBean();
|
||||||
threadMXBean = ManagementFactory.getThreadMXBean();
|
threadMXBean = ManagementFactory.getThreadMXBean();
|
||||||
|
|
||||||
try {
|
boolean enableLastGc = Booleans.parseBoolean(System.getProperty("monitory.jvm.enable_last_gc"), false);
|
||||||
Class sunGcClass = Class.forName("com.sun.management.GarbageCollectorMXBean");
|
if (enableLastGc) {
|
||||||
Class gcInfoClass = Class.forName("com.sun.management.GcInfo");
|
try {
|
||||||
|
Class sunGcClass = Class.forName("com.sun.management.GarbageCollectorMXBean");
|
||||||
|
Class gcInfoClass = Class.forName("com.sun.management.GcInfo");
|
||||||
|
|
||||||
getLastGcInfoMethod = sunGcClass.getDeclaredMethod("getLastGcInfo");
|
getLastGcInfoMethod = sunGcClass.getDeclaredMethod("getLastGcInfo");
|
||||||
getLastGcInfoMethod.setAccessible(true);
|
getLastGcInfoMethod.setAccessible(true);
|
||||||
|
|
||||||
getMemoryUsageBeforeGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageBeforeGc");
|
getMemoryUsageBeforeGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageBeforeGc");
|
||||||
getMemoryUsageBeforeGcMethod.setAccessible(true);
|
getMemoryUsageBeforeGcMethod.setAccessible(true);
|
||||||
getMemoryUsageAfterGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageAfterGc");
|
getMemoryUsageAfterGcMethod = gcInfoClass.getDeclaredMethod("getMemoryUsageAfterGc");
|
||||||
getMemoryUsageAfterGcMethod.setAccessible(true);
|
getMemoryUsageAfterGcMethod.setAccessible(true);
|
||||||
getStartTimeMethod = gcInfoClass.getDeclaredMethod("getStartTime");
|
getStartTimeMethod = gcInfoClass.getDeclaredMethod("getStartTime");
|
||||||
getStartTimeMethod.setAccessible(true);
|
getStartTimeMethod.setAccessible(true);
|
||||||
getEndTimeMethod = gcInfoClass.getDeclaredMethod("getEndTime");
|
getEndTimeMethod = gcInfoClass.getDeclaredMethod("getEndTime");
|
||||||
getEndTimeMethod.setAccessible(true);
|
getEndTimeMethod.setAccessible(true);
|
||||||
getDurationMethod = gcInfoClass.getDeclaredMethod("getDuration");
|
getDurationMethod = gcInfoClass.getDeclaredMethod("getDuration");
|
||||||
getDurationMethod.setAccessible(true);
|
getDurationMethod.setAccessible(true);
|
||||||
|
|
||||||
sunGc = true;
|
} catch (Throwable ex) {
|
||||||
} catch (Throwable ex) {
|
enableLastGc = false;
|
||||||
sunGc = false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JvmStats.enableLastGc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JvmStats jvmStats() {
|
public static JvmStats jvmStats() {
|
||||||
|
@ -111,7 +121,7 @@ public class JvmStats implements Streamable, Serializable, ToXContent {
|
||||||
stats.gc.collectors[i].name = gcMxBean.getName();
|
stats.gc.collectors[i].name = gcMxBean.getName();
|
||||||
stats.gc.collectors[i].collectionCount = gcMxBean.getCollectionCount();
|
stats.gc.collectors[i].collectionCount = gcMxBean.getCollectionCount();
|
||||||
stats.gc.collectors[i].collectionTime = gcMxBean.getCollectionTime();
|
stats.gc.collectors[i].collectionTime = gcMxBean.getCollectionTime();
|
||||||
if (sunGc) {
|
if (enableLastGc) {
|
||||||
try {
|
try {
|
||||||
Object lastGcInfo = getLastGcInfoMethod.invoke(gcMxBean);
|
Object lastGcInfo = getLastGcInfoMethod.invoke(gcMxBean);
|
||||||
if (lastGcInfo != null) {
|
if (lastGcInfo != null) {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. Elastic Search licenses this
|
||||||
|
* file to you 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 org.elasticsearch.test.stress.leaks;
|
||||||
|
|
||||||
|
import org.elasticsearch.monitor.jvm.JvmService;
|
||||||
|
import org.elasticsearch.monitor.network.NetworkService;
|
||||||
|
import org.elasticsearch.monitor.os.OsService;
|
||||||
|
import org.elasticsearch.monitor.process.ProcessService;
|
||||||
|
import org.elasticsearch.node.NodeBuilder;
|
||||||
|
import org.elasticsearch.node.internal.InternalNode;
|
||||||
|
|
||||||
|
public class GenericStatsLeak {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
InternalNode node = (InternalNode) NodeBuilder.nodeBuilder().node();
|
||||||
|
|
||||||
|
JvmService jvmService = node.injector().getInstance(JvmService.class);
|
||||||
|
OsService osService = node.injector().getInstance(OsService.class);
|
||||||
|
ProcessService processService = node.injector().getInstance(ProcessService.class);
|
||||||
|
NetworkService networkService = node.injector().getInstance(NetworkService.class);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
jvmService.stats();
|
||||||
|
osService.stats();
|
||||||
|
processService.stats();
|
||||||
|
networkService.stats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. Elastic Search licenses this
|
||||||
|
* file to you 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 org.elasticsearch.test.stress.leaks;
|
||||||
|
|
||||||
|
import org.elasticsearch.monitor.jvm.JvmStats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test mainly comes to check the native memory leak with getLastGCInfo (which is now
|
||||||
|
* disabled by default).
|
||||||
|
*/
|
||||||
|
public class JvmStatsLeak {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
while (true) {
|
||||||
|
JvmStats.jvmStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue