Skip to content

Commit

Permalink
Use reflection rather than MethodHandles
Browse files Browse the repository at this point in the history
This is a workaround for a bug in the C2 compiler in Java 7 which leads to a segfault
closes elastic#458
  • Loading branch information
felixbarny committed Feb 11, 2019
1 parent 85960af commit 91137e4
Showing 1 changed file with 16 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@
import co.elastic.apm.agent.metrics.MetricRegistry;

import javax.annotation.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -62,28 +60,28 @@ public class SystemMetrics implements LifecycleListener {
private final Class<?> operatingSystemBeanClass;

@Nullable
private final MethodHandle systemCpuUsage;
private final Method systemCpuUsage;

@Nullable
private final MethodHandle processCpuUsage;
private final Method processCpuUsage;

@Nullable
private final MethodHandle freeMemory;
private final Method freeMemory;

@Nullable
private final MethodHandle totalMemory;
private final Method totalMemory;

@Nullable
private final MethodHandle virtualProcessMemory;
private final Method virtualProcessMemory;

public SystemMetrics() {
this.operatingSystemBean = ManagementFactory.getOperatingSystemMXBean();
this.operatingSystemBeanClass = getFirstClassFound(OPERATING_SYSTEM_BEAN_CLASS_NAMES);
this.systemCpuUsage = detectMethod("getSystemCpuLoad", double.class);
this.processCpuUsage = detectMethod("getProcessCpuLoad", double.class);
this.freeMemory = detectMethod("getFreePhysicalMemorySize", long.class);
this.totalMemory = detectMethod("getTotalPhysicalMemorySize", long.class);
this.virtualProcessMemory = detectMethod("getCommittedVirtualMemorySize", long.class);
this.systemCpuUsage = detectMethod("getSystemCpuLoad");
this.processCpuUsage = detectMethod("getProcessCpuLoad");
this.freeMemory = detectMethod("getFreePhysicalMemorySize");
this.totalMemory = detectMethod("getTotalPhysicalMemorySize");
this.virtualProcessMemory = detectMethod("getCommittedVirtualMemorySize");
}

@Override
Expand Down Expand Up @@ -128,24 +126,24 @@ public double get() {
});
}

private double invoke(@Nullable MethodHandle method) {
private double invoke(@Nullable Method method) {
try {
return method != null ? (double) method.invoke(operatingSystemBean) : Double.NaN;
return method != null ? ((Number) method.invoke(operatingSystemBean)).doubleValue() : Double.NaN;
} catch (Throwable e) {
return Double.NaN;
}
}

@Nullable
private MethodHandle detectMethod(String name, Class<?> returnType) {
private Method detectMethod(String name) {
if (operatingSystemBeanClass == null) {
return null;
}
try {
// ensure the Bean we have is actually an instance of the interface
operatingSystemBeanClass.cast(operatingSystemBean);
return MethodHandles.lookup().findVirtual(operatingSystemBeanClass, name, MethodType.methodType(returnType));
} catch (ClassCastException | NoSuchMethodException | SecurityException | IllegalAccessException e) {
return operatingSystemBeanClass.getMethod(name);
} catch (ClassCastException | NoSuchMethodException | SecurityException e) {
return null;
}
}
Expand Down

0 comments on commit 91137e4

Please sign in to comment.