< prev index next >

test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
--- 1,7 ---
  /*
!  * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

*** 25,19 ***
  /*
   * @test
   * @bug 8214781 8293187
   * @summary Test for the -XX:ArchiveHeapTestClass flag
   * @requires vm.debug == true & vm.cds.write.archived.java.heap
!  * @modules java.base/sun.invoke.util java.logging
   * @library /test/jdk/lib/testlibrary /test/lib
   *          /test/hotspot/jtreg/runtime/cds/appcds
   *          /test/hotspot/jtreg/runtime/cds/appcds/test-classes
   * @build ArchiveHeapTestClass Hello pkg.ClassInPackage
   * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar
   *             CDSTestClassA CDSTestClassA$XX CDSTestClassA$YY
   *             CDSTestClassB CDSTestClassC CDSTestClassD
!  *             CDSTestClassE CDSTestClassF CDSTestClassG
   *             pkg.ClassInPackage
   * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar Hello
   * @run driver ArchiveHeapTestClass
   */
  
--- 25,19 ---
  /*
   * @test
   * @bug 8214781 8293187
   * @summary Test for the -XX:ArchiveHeapTestClass flag
   * @requires vm.debug == true & vm.cds.write.archived.java.heap
!  * @modules java.logging
   * @library /test/jdk/lib/testlibrary /test/lib
   *          /test/hotspot/jtreg/runtime/cds/appcds
   *          /test/hotspot/jtreg/runtime/cds/appcds/test-classes
   * @build ArchiveHeapTestClass Hello pkg.ClassInPackage
   * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar
   *             CDSTestClassA CDSTestClassA$XX CDSTestClassA$YY
   *             CDSTestClassB CDSTestClassC CDSTestClassD
!  *             CDSTestClassE CDSTestClassF CDSTestClassG CDSTestClassG$MyEnum CDSTestClassG$Wrapper
   *             pkg.ClassInPackage
   * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar Hello
   * @run driver ArchiveHeapTestClass
   */
  

*** 157,28 ***
  
          testCase("Use a disallowed class: not in java.base module");
          output = dumpBootAndHello(CDSTestClassF_name);
          mustFail(output, "Class java.util.logging.Level not allowed in archive heap");
  
!         if (false) { // JDK-8293187
!             testCase("sun.invoke.util.Wrapper");
!             output = dumpBootAndHello(CDSTestClassG_name);
!             mustSucceed(output);
!         }
      }
  }
  
  class CDSTestClassA {
      static final String output = "CDSTestClassA.<clinit> was executed";
      static Object[] archivedObjects;
      static {
!         archivedObjects = new Object[5];
!         archivedObjects[0] = output;
!         archivedObjects[1] = new CDSTestClassA[0];
!         archivedObjects[2] = new YY();
!         archivedObjects[3] = new int[0];
!         archivedObjects[4] = new int[2][2];
          System.out.println(output);
          System.out.println("CDSTestClassA   module  = " + CDSTestClassA.class.getModule());
          System.out.println("CDSTestClassA   package = " + CDSTestClassA.class.getPackage());
          System.out.println("CDSTestClassA[] module  = " + archivedObjects[1].getClass().getModule());
          System.out.println("CDSTestClassA[] package = " + archivedObjects[1].getClass().getPackage());
--- 157,46 ---
  
          testCase("Use a disallowed class: not in java.base module");
          output = dumpBootAndHello(CDSTestClassF_name);
          mustFail(output, "Class java.util.logging.Level not allowed in archive heap");
  
!         testCase("Complex enums");
!         output = dumpBootAndHello(CDSTestClassG_name, "-XX:+AOTClassLinking", "-Xlog:cds+class=debug");
!         mustSucceed(output);
! 
!         TestCommon.run("-Xbootclasspath/a:" + bootJar, "-cp", appJar, "-Xlog:cds+heap,cds+init",
+                        CDSTestClassG_name)
+             .assertNormalExit("init subgraph " + CDSTestClassG_name,
+                               "Initialized from CDS");
      }
  }
  
  class CDSTestClassA {
      static final String output = "CDSTestClassA.<clinit> was executed";
      static Object[] archivedObjects;
      static {
!         // The usual convention would be to call this here:
!         //     CDS.initializeFromArchive(CDSTestClassA.class);
!         // However, the CDS class is not exported to the unnamed module by default,
!         // and we don't want to use "--add-exports java.base/jdk.internal.misc=ALL-UNNAMED", as
!         // that would disable the archived full module graph, which will disable
!         // CDSConfig::is_using_aot_linked_classes().
+         //
+         // Instead, HeapShared::initialize_test_class_from_archive() will set up the
+         // "archivedObjects" field first, before calling CDSTestClassA.<clinit>. So
+         // if we see that archivedObjects is magically non-null here, that means
+         // it has been restored from the CDS archive.
+         if (archivedObjects == null) {
+             archivedObjects = new Object[5];
+             archivedObjects[0] = output;
+             archivedObjects[1] = new CDSTestClassA[0];
+             archivedObjects[2] = new YY();
+             archivedObjects[3] = new int[0];
+             archivedObjects[4] = new int[2][2];
+         } else {
+             System.out.println("Initialized from CDS");
+         }
          System.out.println(output);
          System.out.println("CDSTestClassA   module  = " + CDSTestClassA.class.getModule());
          System.out.println("CDSTestClassA   package = " + CDSTestClassA.class.getPackage());
          System.out.println("CDSTestClassA[] module  = " + archivedObjects[1].getClass().getModule());
          System.out.println("CDSTestClassA[] package = " + archivedObjects[1].getClass().getPackage());

*** 267,10 ***
  }
  
  class CDSTestClassG {
      static Object[] archivedObjects;
      static {
!         // Not in java.base
!         archivedObjects = new Object[1];
!         archivedObjects[0] = sun.invoke.util.Wrapper.BOOLEAN;
      }
  }
--- 285,145 ---
  }
  
  class CDSTestClassG {
      static Object[] archivedObjects;
      static {
!         if (archivedObjects == null) {
!             archivedObjects = new Object[13];
!             archivedObjects[0] = Wrapper.BOOLEAN;
+             archivedObjects[1] = Wrapper.INT.zero();
+             archivedObjects[2] = Wrapper.DOUBLE.zero();
+             archivedObjects[3] = MyEnum.DUMMY1;
+ 
+             archivedObjects[4] = Boolean.class;
+             archivedObjects[5] = Byte.class;
+             archivedObjects[6] = Character.class;
+             archivedObjects[7] = Short.class;
+             archivedObjects[8] = Integer.class;
+             archivedObjects[9] = Long.class;
+             archivedObjects[10] = Float.class;
+             archivedObjects[11] = Double.class;
+             archivedObjects[12] = Void.class;
+         } else {
+             System.out.println("Initialized from CDS");
+         }
+     }
+ 
+     public static void main(String args[]) {
+         if (archivedObjects[0] != Wrapper.BOOLEAN) {
+             throw new RuntimeException("Huh 0");
+         }
+ 
+         if (archivedObjects[1] != Wrapper.INT.zero()) {
+             throw new RuntimeException("Huh 1");
+         }
+ 
+         if (archivedObjects[2] != Wrapper.DOUBLE.zero()) {
+             throw new RuntimeException("Huh 2");
+         }
+ 
+         if (archivedObjects[3] != MyEnum.DUMMY1) {
+             throw new RuntimeException("Huh 3");
+         }
+ 
+         if (MyEnum.BOOLEAN != true) {
+             throw new RuntimeException("Huh 10.1");
+         }
+         if (MyEnum.BYTE != -128) {
+             throw new RuntimeException("Huh 10.2");
+         }
+         if (MyEnum.CHAR != 'c') {
+             throw new RuntimeException("Huh 10.3");
+         }
+         if (MyEnum.SHORT != -12345) {
+             throw new RuntimeException("Huh 10.4");
+         }
+         if (MyEnum.INT != -123456) {
+             throw new RuntimeException("Huh 10.5");
+         }
+         if (MyEnum.LONG != 0x1234567890L) {
+             throw new RuntimeException("Huh 10.6");
+         }
+         if (MyEnum.LONG2 != -0x1234567890L) {
+             throw new RuntimeException("Huh 10.7");
+         }
+         if (MyEnum.FLOAT != 567891.0f) {
+             throw new RuntimeException("Huh 10.8");
+         }
+         if (MyEnum.DOUBLE != 12345678905678.890) {
+             throw new RuntimeException("Huh 10.9");
+         }
+ 
+         checkClass(4, Boolean.class);
+         checkClass(5, Byte.class);
+         checkClass(6, Character.class);
+         checkClass(7, Short.class);
+         checkClass(8, Integer.class);
+         checkClass(9, Long.class);
+         checkClass(10, Float.class);
+         checkClass(11, Double.class);
+         checkClass(12, Void.class);
+ 
+         System.out.println("Success!");
+     }
+ 
+     static void checkClass(int index, Class c) {
+         if (archivedObjects[index] != c) {
+             throw new RuntimeException("archivedObjects[" + index + "] should be " + c);
+         }
+     }
+ 
+     // Simplified version of sun.invoke.util.Wrapper
+     public enum Wrapper {
+         //        wrapperType      simple     primitiveType  simple     char  emptyArray
+         BOOLEAN(  Boolean.class,   "Boolean", boolean.class, "boolean", 'Z', new boolean[0]),
+         INT    (  Integer.class,   "Integer",     int.class,     "int", 'I', new     int[0]),
+         DOUBLE (   Double.class,    "Double",  double.class,  "double", 'D', new  double[0])
+         ;
+ 
+         public static final int COUNT = 10;
+         private static final Object DOUBLE_ZERO = (Double)(double)0;
+ 
+         private final Class<?> wrapperType;
+         private final Class<?> primitiveType;
+         private final char     basicTypeChar;
+         private final String   basicTypeString;
+         private final Object   emptyArray;
+ 
+         Wrapper(Class<?> wtype,
+                 String wtypeName,
+                 Class<?> ptype,
+                 String ptypeName,
+                 char tchar,
+                 Object emptyArray) {
+             this.wrapperType = wtype;
+             this.primitiveType = ptype;
+             this.basicTypeChar = tchar;
+             this.basicTypeString = String.valueOf(this.basicTypeChar);
+             this.emptyArray = emptyArray;
+         }
+ 
+         public Object zero() {
+             return switch (this) {
+                 case BOOLEAN -> Boolean.FALSE;
+                 case INT -> (Integer)0;
+                 case DOUBLE -> DOUBLE_ZERO;
+                 default -> null;
+             };
+         }
+     }
+ 
+     enum MyEnum {
+         DUMMY1,
+         DUMMY2;
+ 
+         static final boolean BOOLEAN = true;
+         static final byte    BYTE    = -128;
+         static final short   SHORT   = -12345;
+         static final char    CHAR    = 'c';
+         static final int     INT     = -123456;
+         static final long    LONG    =  0x1234567890L;
+         static final long    LONG2   = -0x1234567890L;
+         static final float   FLOAT   = 567891.0f;
+         static final double  DOUBLE  = 12345678905678.890;
      }
  }
< prev index next >