fix JVMMonitor initialization with JDK11 (#8397)

JVMMonitor requires access to jdk.internal.perf.Perf to enable GC
counters, which requires additional JVM arguments with JDK11.

This change adds a fallback in case GC counters cannot be initialized,
and logs a warning message explaining how GC counters can be enabled.
This commit is contained in:
Xavier Léauté 2019-08-25 08:26:58 -04:00 committed by GitHub
parent c626452b47
commit 496dfa3b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 2 deletions

View File

@ -19,9 +19,11 @@
package org.apache.druid.java.util.metrics;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.logger.Logger;
import org.apache.druid.java.util.emitter.service.ServiceEmitter;
import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
import org.gridkit.lab.jvm.perfdata.JStatData;
@ -29,6 +31,7 @@ import org.gridkit.lab.jvm.perfdata.JStatData.LongCounter;
import org.gridkit.lab.jvm.perfdata.JStatData.StringCounter;
import org.gridkit.lab.jvm.perfdata.JStatData.TickCounter;
import javax.annotation.Nullable;
import java.lang.management.BufferPoolMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
@ -40,11 +43,16 @@ import java.util.Map;
public class JvmMonitor extends FeedDefiningMonitor
{
private static final Logger log = new Logger(JvmMonitor.class);
private final Map<String, String[]> dimensions;
private final long pid;
private final GcCounters gcCounters = new GcCounters();
@VisibleForTesting
@Nullable
final GcCounters gcCounters;
@Nullable
private final AllocationMetricCollector collector;
public JvmMonitor()
@ -69,6 +77,7 @@ public class JvmMonitor extends FeedDefiningMonitor
this.dimensions = ImmutableMap.copyOf(dimensions);
this.pid = Preconditions.checkNotNull(pidDiscoverer).getPid();
this.collector = AllocationMetricCollectors.getAllocationMetricCollector();
this.gcCounters = tryCreateGcCounters();
}
@Override
@ -146,7 +155,25 @@ public class JvmMonitor extends FeedDefiningMonitor
private void emitGcMetrics(ServiceEmitter emitter)
{
gcCounters.emit(emitter, dimensions);
if (gcCounters != null) {
gcCounters.emit(emitter, dimensions);
}
}
@Nullable
private GcCounters tryCreateGcCounters()
{
try {
return new GcCounters();
}
catch (RuntimeException e) {
// in JDK11 jdk.internal.perf.Perf is not accessible, unless
// --add-exports java.base/jdk.internal.perf=ALL-UNNAMED is set
log.warn("Cannot initialize GC counters. If running JDK11 and above,"
+ " add --add-exports java.base/jdk.internal.perf=ALL-UNNAMED"
+ " to the JVM arguments to enable GC counters.");
}
return null;
}
/**

View File

@ -24,6 +24,7 @@ import org.apache.druid.java.util.emitter.core.Event;
import org.apache.druid.java.util.emitter.service.ServiceEmitter;
import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import java.util.List;
@ -39,6 +40,8 @@ public class JvmMonitorTest
final ServiceEmitter serviceEmitter = new ServiceEmitter("test", "localhost", emitter);
serviceEmitter.start();
final JvmMonitor jvmMonitor = new JvmMonitor();
// skip tests if gc counters fail to initialize with this JDK
Assume.assumeNotNull(jvmMonitor.gcCounters);
while (true) {
// generate some garbage to see gc counters incremented