package org.graalvm.compiler.hotspot.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.util.Arrays;
import javax.management.Attribute;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.test.GraalTest;
import org.graalvm.util.EconomicMap;
import org.junit.Assume;
import org.junit.Test;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class HotSpotGraalMBeanTest {
public HotSpotGraalMBeanTest() {
Assume.assumeTrue(GraalTest.Java8OrEarlier);
}
@Test
public void registration() throws Exception {
ObjectName name;
Field field = null;
try {
field = stopMBeanServer();
} catch (Exception ex) {
if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
return;
}
}
assertNull("The platformMBeanServer isn't initialized now", field.get(null));
HotSpotGraalMBean bean = HotSpotGraalMBean.create(null);
assertNotNull("Bean created", bean);
assertNull("It is not registered yet", bean.ensureRegistered(true));
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
assertNotNull("Now the bean thinks it is registered", name = bean.ensureRegistered(true));
assertNotNull("And the bean is found", server.getObjectInstance(name));
}
private static Field stopMBeanServer() throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException {
final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
field.setAccessible(true);
field.set(null, null);
return field;
}
@Test
public void readBeanInfo() throws Exception {
ObjectName name;
assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectInstance bean = server.getObjectInstance(name);
assertNotNull("Bean is registered", bean);
MBeanInfo info = server.getMBeanInfo(name);
assertNotNull("Info is found", info);
MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info);
assertNotNull("PrintCompilation found", printCompilation);
assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
Attribute printOn = new Attribute(printCompilation.getName(), Boolean.TRUE);
Object before = server.getAttribute(name, printCompilation.getName());
server.setAttribute(name, printOn);
Object after = server.getAttribute(name, printCompilation.getName());
assertNull("Default value was not set", before);
assertEquals("Changed to on", Boolean.TRUE, after);
}
private static Object findAttributeInfo(String attrName, Object info) {
MBeanAttributeInfo printCompilation = null;
for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) {
if (attr.getName().equals(attrName)) {
assertTrue("Readable", attr.isReadable());
assertTrue("Writable", attr.isWritable());
printCompilation = attr;
break;
}
}
return printCompilation;
}
@Test
public void optionsAreCached() throws Exception {
ObjectName name;
assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
OptionValues original = new OptionValues(EconomicMap.create());
assertSame(original, realBean.optionsFor(original, null));
assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectInstance bean = server.getObjectInstance(name);
assertNotNull("Bean is registered", bean);
MBeanInfo info = server.getMBeanInfo(name);
assertNotNull("Info is found", info);
MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
Attribute dumpTo1 = new Attribute(dump.getName(), 1);
server.setAttribute(name, dumpTo1);
Object after = server.getAttribute(name, dump.getName());
assertEquals(1, after);
final OptionValues modified1 = realBean.optionsFor(original, null);
assertNotSame(original, modified1);
final OptionValues modified2 = realBean.optionsFor(original, null);
assertSame("Options are cached", modified1, modified2);
}
@Test
public void dumpOperation() throws Exception {
Field field = null;
try {
field = stopMBeanServer();
} catch (Exception ex) {
if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
return;
}
}
assertNull("The platformMBeanServer isn't initialized now", field.get(null));
ObjectName name;
assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectInstance bean = server.getObjectInstance(name);
assertNotNull("Bean is registered", bean);
MBeanInfo info = server.getMBeanInfo(name);
assertNotNull("Info is found", info);
final MBeanOperationInfo[] arr = info.getOperations();
assertEquals("Currently three overloads", 3, arr.length);
MBeanOperationInfo dumpOp = null;
for (int i = 0; i < arr.length; i++) {
assertEquals("dumpMethod", arr[i].getName());
if (arr[i].getSignature().length == 3) {
dumpOp = arr[i];
}
}
assertNotNull("three args variant found", dumpOp);
server.invoke(name, "dumpMethod", new Object[]{
"java.util.Arrays", "asList", ":3"
}, null);
MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
Attribute dumpTo1 = new Attribute(dump.getName(), "");
server.setAttribute(name, dumpTo1);
Object after = server.getAttribute(name, dump.getName());
assertEquals("", after);
OptionValues empty = new OptionValues(EconomicMap.create());
OptionValues unsetDump = realBean.optionsFor(empty, null);
final MetaAccessProvider metaAccess = jdk.vm.ci.runtime.JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Arrays.class.getMethod("asList", Object[].class));
final OptionValues forMethod = realBean.optionsFor(unsetDump, method);
assertNotSame(unsetDump, forMethod);
Object nothing = unsetDump.getMap().get(DebugOptions.Dump);
assertEquals("Empty string", "", nothing);
Object specialValue = forMethod.getMap().get(DebugOptions.Dump);
assertEquals(":3", specialValue);
OptionValues normalMethod = realBean.optionsFor(unsetDump, null);
Object noSpecialValue = normalMethod.getMap().get(DebugOptions.Dump);
assertEquals("Empty string", "", noSpecialValue);
}
}