1 /*
   2  * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.hotspot.test;
  24 
  25 import static org.junit.Assert.assertEquals;
  26 import static org.junit.Assert.assertNotNull;
  27 import static org.junit.Assert.assertNotSame;
  28 import static org.junit.Assert.assertNull;
  29 import static org.junit.Assert.assertSame;
  30 import static org.junit.Assert.assertTrue;
  31 
  32 import java.lang.management.ManagementFactory;
  33 import java.lang.reflect.Field;
  34 
  35 import java.util.Arrays;
  36 import javax.management.Attribute;
  37 import javax.management.MBeanAttributeInfo;
  38 import javax.management.MBeanInfo;
  39 import javax.management.MBeanOperationInfo;
  40 import javax.management.MBeanServer;
  41 import javax.management.ObjectInstance;
  42 import javax.management.ObjectName;
  43 
  44 import org.graalvm.compiler.debug.DebugOptions;
  45 import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
  46 import org.graalvm.compiler.options.OptionValues;
  47 import org.graalvm.compiler.test.GraalTest;
  48 import org.graalvm.util.EconomicMap;
  49 import org.junit.Assume;
  50 import org.junit.Test;
  51 
  52 import jdk.vm.ci.meta.MetaAccessProvider;
  53 import jdk.vm.ci.meta.ResolvedJavaMethod;
  54 
  55 public class HotSpotGraalMBeanTest {
  56 
  57     public HotSpotGraalMBeanTest() {
  58         // No support for registering Graal MBean yet on JDK9 (GR-4025). We cannot
  59         // rely on an exception being thrown when accessing ManagementFactory.platformMBeanServer
  60         // via reflection as recent JDK9 changes now allow this and issue a warning instead.
  61         Assume.assumeTrue(GraalTest.Java8OrEarlier);
  62     }
  63 
  64     @Test
  65     public void registration() throws Exception {
  66         ObjectName name;
  67 
  68         Field field = null;
  69         try {
  70             field = stopMBeanServer();
  71         } catch (Exception ex) {
  72             if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
  73                 // skip on JDK9
  74                 return;
  75             }
  76         }
  77         assertNull("The platformMBeanServer isn't initialized now", field.get(null));
  78 
  79         HotSpotGraalMBean bean = HotSpotGraalMBean.create(null);
  80         assertNotNull("Bean created", bean);
  81 
  82         assertNull("It is not registered yet", bean.ensureRegistered(true));
  83 
  84         MBeanServer server = ManagementFactory.getPlatformMBeanServer();
  85 
  86         assertNotNull("Now the bean thinks it is registered", name = bean.ensureRegistered(true));
  87 
  88         assertNotNull("And the bean is found", server.getObjectInstance(name));
  89     }
  90 
  91     private static Field stopMBeanServer() throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException {
  92         final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
  93         field.setAccessible(true);
  94         field.set(null, null);
  95         return field;
  96     }
  97 
  98     @Test
  99     public void readBeanInfo() throws Exception {
 100         ObjectName name;
 101 
 102         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 103 
 104         HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 105         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
 106         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 107 
 108         ObjectInstance bean = server.getObjectInstance(name);
 109         assertNotNull("Bean is registered", bean);
 110         MBeanInfo info = server.getMBeanInfo(name);
 111         assertNotNull("Info is found", info);
 112 
 113         MBeanAttributeInfo printCompilation = findAttributeInfo("PrintCompilation", info);
 114         assertNotNull("PrintCompilation found", printCompilation);
 115         assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
 116 
 117         Attribute printOn = new Attribute(printCompilation.getName(), Boolean.TRUE);
 118 
 119         Object before = server.getAttribute(name, printCompilation.getName());
 120         server.setAttribute(name, printOn);
 121         Object after = server.getAttribute(name, printCompilation.getName());
 122 
 123         assertNull("Default value was not set", before);
 124         assertEquals("Changed to on", Boolean.TRUE, after);
 125     }
 126 
 127     private static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
 128         MBeanAttributeInfo printCompilation = null;
 129         for (MBeanAttributeInfo attr : info.getAttributes()) {
 130             if (attr.getName().equals(attrName)) {
 131                 assertTrue("Readable", attr.isReadable());
 132                 assertTrue("Writable", attr.isWritable());
 133                 printCompilation = attr;
 134                 break;
 135             }
 136         }
 137         return printCompilation;
 138     }
 139 
 140     @Test
 141     public void optionsAreCached() throws Exception {
 142         ObjectName name;
 143 
 144         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 145 
 146         HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 147 
 148         OptionValues original = new OptionValues(EconomicMap.create());
 149 
 150         assertSame(original, realBean.optionsFor(original, null));
 151 
 152         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
 153         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 154 
 155         ObjectInstance bean = server.getObjectInstance(name);
 156         assertNotNull("Bean is registered", bean);
 157         MBeanInfo info = server.getMBeanInfo(name);
 158         assertNotNull("Info is found", info);
 159 
 160         MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
 161 
 162         Attribute dumpTo1 = new Attribute(dump.getName(), 1);
 163 
 164         server.setAttribute(name, dumpTo1);
 165         Object after = server.getAttribute(name, dump.getName());
 166         assertEquals(1, after);
 167 
 168         final OptionValues modified1 = realBean.optionsFor(original, null);
 169         assertNotSame(original, modified1);
 170         final OptionValues modified2 = realBean.optionsFor(original, null);
 171         assertSame("Options are cached", modified1, modified2);
 172 
 173     }
 174 
 175     @Test
 176     public void dumpOperation() throws Exception {
 177         Field field = null;
 178         try {
 179             field = stopMBeanServer();
 180         } catch (Exception ex) {
 181             if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
 182                 // skip on JDK9
 183                 return;
 184             }
 185         }
 186         assertNull("The platformMBeanServer isn't initialized now", field.get(null));
 187 
 188         ObjectName name;
 189 
 190         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 191 
 192         HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 193 
 194         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
 195         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 196 
 197         ObjectInstance bean = server.getObjectInstance(name);
 198         assertNotNull("Bean is registered", bean);
 199 
 200         MBeanInfo info = server.getMBeanInfo(name);
 201         assertNotNull("Info is found", info);
 202 
 203         final MBeanOperationInfo[] arr = info.getOperations();
 204         assertEquals("Currently three overloads", 3, arr.length);
 205         MBeanOperationInfo dumpOp = null;
 206         for (int i = 0; i < arr.length; i++) {
 207             assertEquals("dumpMethod", arr[i].getName());
 208             if (arr[i].getSignature().length == 3) {
 209                 dumpOp = arr[i];
 210             }
 211         }
 212         assertNotNull("three args variant found", dumpOp);
 213 
 214         server.invoke(name, "dumpMethod", new Object[]{
 215                         "java.util.Arrays", "asList", ":3"
 216         }, null);
 217 
 218         MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
 219         Attribute dumpTo1 = new Attribute(dump.getName(), "");
 220         server.setAttribute(name, dumpTo1);
 221         Object after = server.getAttribute(name, dump.getName());
 222         assertEquals("", after);
 223 
 224         OptionValues empty = new OptionValues(EconomicMap.create());
 225         OptionValues unsetDump = realBean.optionsFor(empty, null);
 226         final MetaAccessProvider metaAccess = jdk.vm.ci.runtime.JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
 227         ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Arrays.class.getMethod("asList", Object[].class));
 228         final OptionValues forMethod = realBean.optionsFor(unsetDump, method);
 229         assertNotSame(unsetDump, forMethod);
 230         Object nothing = unsetDump.getMap().get(DebugOptions.Dump);
 231         assertEquals("Empty string", "", nothing);
 232 
 233         Object specialValue = forMethod.getMap().get(DebugOptions.Dump);
 234         assertEquals(":3", specialValue);
 235 
 236         OptionValues normalMethod = realBean.optionsFor(unsetDump, null);
 237         Object noSpecialValue = normalMethod.getMap().get(DebugOptions.Dump);
 238         assertEquals("Empty string", "", noSpecialValue);
 239     }
 240 
 241 }