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 java.lang.annotation.Annotation;
  26 import java.lang.management.ManagementFactory;
  27 import java.lang.reflect.Field;
  28 import java.lang.reflect.Type;
  29 import javax.management.Attribute;
  30 import javax.management.MBeanAttributeInfo;
  31 import javax.management.MBeanInfo;
  32 import javax.management.MBeanOperationInfo;
  33 import javax.management.MBeanServer;
  34 import javax.management.ObjectInstance;
  35 import javax.management.ObjectName;
  36 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
  37 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
  38 import jdk.vm.ci.meta.Assumptions;
  39 import jdk.vm.ci.meta.Constant;
  40 import jdk.vm.ci.meta.ConstantPool;
  41 import jdk.vm.ci.meta.ExceptionHandler;
  42 import jdk.vm.ci.meta.JavaConstant;
  43 import jdk.vm.ci.meta.JavaKind;
  44 import jdk.vm.ci.meta.LineNumberTable;
  45 import jdk.vm.ci.meta.LocalVariableTable;
  46 import jdk.vm.ci.meta.ProfilingInfo;
  47 import jdk.vm.ci.meta.ResolvedJavaField;
  48 import jdk.vm.ci.meta.ResolvedJavaMethod;
  49 import jdk.vm.ci.meta.ResolvedJavaType;
  50 import jdk.vm.ci.meta.Signature;
  51 import jdk.vm.ci.meta.SpeculationLog;
  52 import org.graalvm.compiler.debug.GraalDebugConfig;
  53 import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
  54 import org.graalvm.compiler.options.OptionValues;
  55 import org.graalvm.util.EconomicMap;
  56 import static org.junit.Assert.assertEquals;
  57 import static org.junit.Assert.assertNotNull;
  58 import static org.junit.Assert.assertNotSame;
  59 import static org.junit.Assert.assertNull;
  60 import static org.junit.Assert.assertSame;
  61 import static org.junit.Assert.assertTrue;
  62 import org.junit.Test;
  63 
  64 public class HotSpotGraalMBeanTest {
  65     @Test
  66     public void registration() throws Exception {
  67         ObjectName name;
  68 
  69         Field field = null;
  70         try {
  71             field = stopMBeanServer();
  72         } catch (Exception ex) {
  73             if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
  74                 // skip on JDK9
  75                 return;
  76             }
  77         }
  78         assertNull("The platformMBeanServer isn't initialized now", field.get(null));
  79 
  80         HotSpotGraalMBean bean = HotSpotGraalMBean.create(null);
  81         assertNotNull("Bean created", bean);
  82 
  83         assertNull("It is not registered yet", bean.ensureRegistered(true));
  84 
  85         MBeanServer server = ManagementFactory.getPlatformMBeanServer();
  86 
  87         assertNotNull("Now the bean thinks it is registered", name = bean.ensureRegistered(true));
  88 
  89         assertNotNull("And the bean is found", server.getObjectInstance(name));
  90     }
  91 
  92     private static Field stopMBeanServer() throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException {
  93         final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
  94         field.setAccessible(true);
  95         field.set(null, null);
  96         return field;
  97     }
  98 
  99     @Test
 100     public void readBeanInfo() throws Exception {
 101         ObjectName name;
 102 
 103         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 104 
 105         HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 106         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
 107         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 108 
 109         ObjectInstance bean = server.getObjectInstance(name);
 110         assertNotNull("Bean is registered", bean);
 111         MBeanInfo info = server.getMBeanInfo(name);
 112         assertNotNull("Info is found", info);
 113 
 114         MBeanAttributeInfo printCompilation = findAttributeInfo("PrintCompilation", info);
 115         assertNotNull("PrintCompilation found", printCompilation);
 116         assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
 117 
 118         Attribute printOn = new Attribute(printCompilation.getName(), Boolean.TRUE);
 119 
 120         Object before = server.getAttribute(name, printCompilation.getName());
 121         server.setAttribute(name, printOn);
 122         Object after = server.getAttribute(name, printCompilation.getName());
 123 
 124         assertNull("Default value was not set", before);
 125         assertEquals("Changed to on", Boolean.TRUE, after);
 126     }
 127 
 128     private static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
 129         MBeanAttributeInfo printCompilation = null;
 130         for (MBeanAttributeInfo attr : info.getAttributes()) {
 131             if (attr.getName().equals(attrName)) {
 132                 assertTrue("Readable", attr.isReadable());
 133                 assertTrue("Writable", attr.isWritable());
 134                 printCompilation = attr;
 135                 break;
 136             }
 137         }
 138         return printCompilation;
 139     }
 140 
 141     @Test
 142     public void optionsAreCached() throws Exception {
 143         ObjectName name;
 144 
 145         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 146 
 147         HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 148 
 149         OptionValues original = new OptionValues(EconomicMap.create());
 150 
 151         assertSame(original, realBean.optionsFor(original, null));
 152 
 153         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
 154         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 155 
 156         ObjectInstance bean = server.getObjectInstance(name);
 157         assertNotNull("Bean is registered", bean);
 158         MBeanInfo info = server.getMBeanInfo(name);
 159         assertNotNull("Info is found", info);
 160 
 161         MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
 162 
 163         Attribute dumpTo1 = new Attribute(dump.getName(), 1);
 164 
 165         server.setAttribute(name, dumpTo1);
 166         Object after = server.getAttribute(name, dump.getName());
 167         assertEquals(1, after);
 168 
 169         final OptionValues modified1 = realBean.optionsFor(original, null);
 170         assertNotSame(original, modified1);
 171         final OptionValues modified2 = realBean.optionsFor(original, null);
 172         assertSame("Options are cached", modified1, modified2);
 173 
 174     }
 175 
 176     @Test
 177     public void dumpOperation() throws Exception {
 178         Field field = null;
 179         try {
 180             field = stopMBeanServer();
 181         } catch (Exception ex) {
 182             if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
 183                 // skip on JDK9
 184                 return;
 185             }
 186         }
 187         assertNull("The platformMBeanServer isn't initialized now", field.get(null));
 188 
 189         ObjectName name;
 190 
 191         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 192 
 193         HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 194 
 195         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
 196         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 197 
 198         ObjectInstance bean = server.getObjectInstance(name);
 199         assertNotNull("Bean is registered", bean);
 200 
 201         MBeanInfo info = server.getMBeanInfo(name);
 202         assertNotNull("Info is found", info);
 203 
 204         final MBeanOperationInfo[] arr = info.getOperations();
 205         assertEquals("Currently three overloads", 3, arr.length);
 206         MBeanOperationInfo dumpOp = null;
 207         for (int i = 0; i < arr.length; i++) {
 208             assertEquals("dumpMethod", arr[i].getName());
 209             if (arr[i].getSignature().length == 3) {
 210                 dumpOp = arr[i];
 211             }
 212         }
 213         assertNotNull("three args variant found", dumpOp);
 214 
 215         server.invoke(name, "dumpMethod", new Object[]{
 216                         "java.util.Arrays", "asList", ":3"
 217         }, null);
 218 
 219         MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
 220         Attribute dumpTo1 = new Attribute(dump.getName(), "");
 221         server.setAttribute(name, dumpTo1);
 222         Object after = server.getAttribute(name, dump.getName());
 223         assertEquals("", after);
 224 
 225         OptionValues empty = new OptionValues(EconomicMap.create());
 226         OptionValues unsetDump = realBean.optionsFor(empty, null);
 227 
 228         final OptionValues forMethod = realBean.optionsFor(unsetDump, new MockResolvedJavaMethod());
 229         assertNotSame(unsetDump, forMethod);
 230         Object nothing = unsetDump.getMap().get(GraalDebugConfig.Options.Dump);
 231         assertEquals("Empty string", "", nothing);
 232 
 233         Object specialValue = forMethod.getMap().get(GraalDebugConfig.Options.Dump);
 234         assertEquals(":3", specialValue);
 235 
 236         OptionValues normalMethod = realBean.optionsFor(unsetDump, null);
 237         Object noSpecialValue = normalMethod.getMap().get(GraalDebugConfig.Options.Dump);
 238         assertEquals("Empty string", "", noSpecialValue);
 239     }
 240 
 241     private static class MockResolvedJavaMethod implements HotSpotResolvedJavaMethod {
 242         MockResolvedJavaMethod() {
 243         }
 244 
 245         @Override
 246         public boolean isCallerSensitive() {
 247             throw new UnsupportedOperationException();
 248         }
 249 
 250         @Override
 251         public HotSpotResolvedObjectType getDeclaringClass() {
 252             return new MockResolvedObjectType();
 253         }
 254 
 255         @Override
 256         public boolean isForceInline() {
 257             throw new UnsupportedOperationException();
 258         }
 259 
 260         @Override
 261         public boolean hasReservedStackAccess() {
 262             throw new UnsupportedOperationException();
 263         }
 264 
 265         @Override
 266         public void setNotInlineable() {
 267             throw new UnsupportedOperationException();
 268         }
 269 
 270         @Override
 271         public boolean ignoredBySecurityStackWalk() {
 272             throw new UnsupportedOperationException();
 273         }
 274 
 275         @Override
 276         public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) {
 277             throw new UnsupportedOperationException();
 278         }
 279 
 280         @Override
 281         public boolean hasCompiledCode() {
 282             throw new UnsupportedOperationException();
 283         }
 284 
 285         @Override
 286         public boolean hasCompiledCodeAtLevel(int level) {
 287             throw new UnsupportedOperationException();
 288         }
 289 
 290         @Override
 291         public int vtableEntryOffset(ResolvedJavaType resolved) {
 292             throw new UnsupportedOperationException();
 293         }
 294 
 295         @Override
 296         public int intrinsicId() {
 297             throw new UnsupportedOperationException();
 298         }
 299 
 300         @Override
 301         public int allocateCompileId(int entryBCI) {
 302             throw new UnsupportedOperationException();
 303         }
 304 
 305         @Override
 306         public boolean hasCodeAtLevel(int entryBCI, int level) {
 307             throw new UnsupportedOperationException();
 308         }
 309 
 310         @Override
 311         public byte[] getCode() {
 312             throw new UnsupportedOperationException();
 313         }
 314 
 315         @Override
 316         public int getCodeSize() {
 317             throw new UnsupportedOperationException();
 318         }
 319 
 320         @Override
 321         public int getMaxLocals() {
 322             throw new UnsupportedOperationException();
 323         }
 324 
 325         @Override
 326         public int getMaxStackSize() {
 327             throw new UnsupportedOperationException();
 328         }
 329 
 330         @Override
 331         public boolean isSynthetic() {
 332             throw new UnsupportedOperationException();
 333         }
 334 
 335         @Override
 336         public boolean isVarArgs() {
 337             throw new UnsupportedOperationException();
 338         }
 339 
 340         @Override
 341         public boolean isBridge() {
 342             throw new UnsupportedOperationException();
 343         }
 344 
 345         @Override
 346         public boolean isClassInitializer() {
 347             throw new UnsupportedOperationException();
 348         }
 349 
 350         @Override
 351         public boolean isConstructor() {
 352             throw new UnsupportedOperationException();
 353         }
 354 
 355         @Override
 356         public boolean canBeStaticallyBound() {
 357             throw new UnsupportedOperationException();
 358         }
 359 
 360         @Override
 361         public ExceptionHandler[] getExceptionHandlers() {
 362             throw new UnsupportedOperationException();
 363         }
 364 
 365         @Override
 366         public StackTraceElement asStackTraceElement(int bci) {
 367             throw new UnsupportedOperationException();
 368         }
 369 
 370         @Override
 371         public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) {
 372             throw new UnsupportedOperationException();
 373         }
 374 
 375         @Override
 376         public void reprofile() {
 377             throw new UnsupportedOperationException();
 378         }
 379 
 380         @Override
 381         public ConstantPool getConstantPool() {
 382             throw new UnsupportedOperationException();
 383         }
 384 
 385         @Override
 386         public Annotation[][] getParameterAnnotations() {
 387             throw new UnsupportedOperationException();
 388         }
 389 
 390         @Override
 391         public Type[] getGenericParameterTypes() {
 392             throw new UnsupportedOperationException();
 393         }
 394 
 395         @Override
 396         public boolean canBeInlined() {
 397             throw new UnsupportedOperationException();
 398         }
 399 
 400         @Override
 401         public boolean hasNeverInlineDirective() {
 402             throw new UnsupportedOperationException();
 403         }
 404 
 405         @Override
 406         public boolean shouldBeInlined() {
 407             throw new UnsupportedOperationException();
 408         }
 409 
 410         @Override
 411         public LineNumberTable getLineNumberTable() {
 412             throw new UnsupportedOperationException();
 413         }
 414 
 415         @Override
 416         public LocalVariableTable getLocalVariableTable() {
 417             throw new UnsupportedOperationException();
 418         }
 419 
 420         @Override
 421         public Constant getEncoding() {
 422             throw new UnsupportedOperationException();
 423         }
 424 
 425         @Override
 426         public boolean isInVirtualMethodTable(ResolvedJavaType resolved) {
 427             throw new UnsupportedOperationException();
 428         }
 429 
 430         @Override
 431         public SpeculationLog getSpeculationLog() {
 432             throw new UnsupportedOperationException();
 433         }
 434 
 435         @Override
 436         public String getName() {
 437             return "asList";
 438         }
 439 
 440         @Override
 441         public Signature getSignature() {
 442             throw new UnsupportedOperationException();
 443         }
 444 
 445         @Override
 446         public int getModifiers() {
 447             throw new UnsupportedOperationException();
 448         }
 449 
 450         @Override
 451         public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 452             throw new UnsupportedOperationException();
 453         }
 454 
 455         @Override
 456         public Annotation[] getAnnotations() {
 457             throw new UnsupportedOperationException();
 458         }
 459 
 460         @Override
 461         public Annotation[] getDeclaredAnnotations() {
 462             throw new UnsupportedOperationException();
 463         }
 464 
 465         @Override
 466         public boolean isIntrinsicCandidate() {
 467             return true;
 468         }
 469 
 470         private static class MockResolvedObjectType implements HotSpotResolvedObjectType {
 471             MockResolvedObjectType() {
 472             }
 473 
 474             @Override
 475             public long getFingerprint() {
 476                 return 0L;
 477             }
 478 
 479             @Override
 480             public HotSpotResolvedObjectType getArrayClass() {
 481                 throw new UnsupportedOperationException();
 482             }
 483 
 484             @Override
 485             public ResolvedJavaType getComponentType() {
 486                 throw new UnsupportedOperationException();
 487             }
 488 
 489             @Override
 490             public Assumptions.AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
 491                 throw new UnsupportedOperationException();
 492             }
 493 
 494             @Override
 495             public HotSpotResolvedObjectType getSuperclass() {
 496                 throw new UnsupportedOperationException();
 497             }
 498 
 499             @Override
 500             public HotSpotResolvedObjectType[] getInterfaces() {
 501                 throw new UnsupportedOperationException();
 502             }
 503 
 504             @Override
 505             public HotSpotResolvedObjectType getSupertype() {
 506                 throw new UnsupportedOperationException();
 507             }
 508 
 509             @Override
 510             public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
 511                 throw new UnsupportedOperationException();
 512             }
 513 
 514             @Override
 515             public ConstantPool getConstantPool() {
 516                 throw new UnsupportedOperationException();
 517             }
 518 
 519             @Override
 520             public int instanceSize() {
 521                 throw new UnsupportedOperationException();
 522             }
 523 
 524             @Override
 525             public int getVtableLength() {
 526                 throw new UnsupportedOperationException();
 527             }
 528 
 529             @Override
 530             public Assumptions.AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method) {
 531                 throw new UnsupportedOperationException();
 532             }
 533 
 534             @Override
 535             public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) {
 536                 throw new UnsupportedOperationException();
 537             }
 538 
 539             @Override
 540             public Constant klass() {
 541                 throw new UnsupportedOperationException();
 542             }
 543 
 544             @Override
 545             public boolean isPrimaryType() {
 546                 throw new UnsupportedOperationException();
 547             }
 548 
 549             @Override
 550             public int superCheckOffset() {
 551                 throw new UnsupportedOperationException();
 552             }
 553 
 554             @Override
 555             public long prototypeMarkWord() {
 556                 throw new UnsupportedOperationException();
 557             }
 558 
 559             @Override
 560             public int layoutHelper() {
 561                 throw new UnsupportedOperationException();
 562             }
 563 
 564             @Override
 565             public HotSpotResolvedObjectType getEnclosingType() {
 566                 throw new UnsupportedOperationException();
 567             }
 568 
 569             @Override
 570             public ResolvedJavaMethod getClassInitializer() {
 571                 throw new UnsupportedOperationException();
 572             }
 573 
 574             @Override
 575             public boolean hasFinalizer() {
 576                 throw new UnsupportedOperationException();
 577             }
 578 
 579             @Override
 580             public Assumptions.AssumptionResult<Boolean> hasFinalizableSubclass() {
 581                 throw new UnsupportedOperationException();
 582             }
 583 
 584             @Override
 585             public boolean isInterface() {
 586                 throw new UnsupportedOperationException();
 587             }
 588 
 589             @Override
 590             public boolean isInstanceClass() {
 591                 throw new UnsupportedOperationException();
 592             }
 593 
 594             @Override
 595             public boolean isInitialized() {
 596                 throw new UnsupportedOperationException();
 597             }
 598 
 599             @Override
 600             public void initialize() {
 601                 throw new UnsupportedOperationException();
 602             }
 603 
 604             @Override
 605             public boolean isLinked() {
 606                 throw new UnsupportedOperationException();
 607             }
 608 
 609             @Override
 610             public boolean isAssignableFrom(ResolvedJavaType other) {
 611                 throw new UnsupportedOperationException();
 612             }
 613 
 614             @Override
 615             public boolean isInstance(JavaConstant obj) {
 616                 throw new UnsupportedOperationException();
 617             }
 618 
 619             @Override
 620             public ResolvedJavaType getSingleImplementor() {
 621                 throw new UnsupportedOperationException();
 622             }
 623 
 624             @Override
 625             public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
 626                 throw new UnsupportedOperationException();
 627             }
 628 
 629             @Override
 630             public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
 631                 throw new UnsupportedOperationException();
 632             }
 633 
 634             @Override
 635             public ResolvedJavaField[] getStaticFields() {
 636                 throw new UnsupportedOperationException();
 637             }
 638 
 639             @Override
 640             public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind) {
 641                 throw new UnsupportedOperationException();
 642             }
 643 
 644             @Override
 645             public String getSourceFileName() {
 646                 throw new UnsupportedOperationException();
 647             }
 648 
 649             @Override
 650             public boolean isLocal() {
 651                 throw new UnsupportedOperationException();
 652             }
 653 
 654             @Override
 655             public boolean isMember() {
 656                 throw new UnsupportedOperationException();
 657             }
 658 
 659             @Override
 660             public ResolvedJavaMethod[] getDeclaredConstructors() {
 661                 throw new UnsupportedOperationException();
 662             }
 663 
 664             @Override
 665             public ResolvedJavaMethod[] getDeclaredMethods() {
 666                 throw new UnsupportedOperationException();
 667             }
 668 
 669             @Override
 670             public boolean isCloneableWithAllocation() {
 671                 throw new UnsupportedOperationException();
 672             }
 673 
 674             @Override
 675             public String getName() {
 676                 return "Ljava/util/Arrays;";
 677             }
 678 
 679             @Override
 680             public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
 681                 throw new UnsupportedOperationException();
 682             }
 683 
 684             @Override
 685             public int getModifiers() {
 686                 throw new UnsupportedOperationException();
 687             }
 688 
 689             @Override
 690             public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 691                 throw new UnsupportedOperationException();
 692             }
 693 
 694             @Override
 695             public Annotation[] getAnnotations() {
 696                 throw new UnsupportedOperationException();
 697             }
 698 
 699             @Override
 700             public Annotation[] getDeclaredAnnotations() {
 701                 throw new UnsupportedOperationException();
 702             }
 703         }
 704     }
 705 }