< prev index next >

src/java.base/share/classes/jdk/internal/misc/CDS.java

Print this page

 35 import java.net.URLClassLoader;
 36 import java.nio.file.InvalidPathException;
 37 import java.nio.file.Path;
 38 import java.util.Arrays;
 39 import java.util.ArrayList;
 40 import java.util.List;
 41 import java.util.Map;
 42 import java.util.Objects;
 43 import java.util.stream.Stream;
 44 
 45 import jdk.internal.access.SharedSecrets;
 46 import jdk.internal.util.StaticProperty;
 47 
 48 public class CDS {
 49     // Must be in sync with cdsConfig.hpp
 50     private static final int IS_DUMPING_ARCHIVE              = 1 << 0;
 51     private static final int IS_DUMPING_METHOD_HANDLES       = 1 << 1;
 52     private static final int IS_DUMPING_STATIC_ARCHIVE       = 1 << 2;
 53     private static final int IS_LOGGING_LAMBDA_FORM_INVOKERS = 1 << 3;
 54     private static final int IS_USING_ARCHIVE                = 1 << 4;




 55     private static final int configStatus = getCDSConfigStatus();
 56 
 57     /**
 58      * Should we log the use of lambda form invokers?
 59      */
 60     public static boolean isLoggingLambdaFormInvokers() {
 61         return (configStatus & IS_LOGGING_LAMBDA_FORM_INVOKERS) != 0;
 62     }
 63 
 64     /**
 65       * Is the VM writing to a (static or dynamic) CDS archive.
 66       */
 67     public static boolean isDumpingArchive() {
 68         return (configStatus & IS_DUMPING_ARCHIVE) != 0;
 69     }
 70 
 71     /**
 72       * Is the VM using at least one CDS archive?
 73       */
 74     public static boolean isUsingArchive() {
 75         return (configStatus & IS_USING_ARCHIVE) != 0;
 76     }
 77 
 78     /**
 79       * Is dumping static archive.
 80       */
 81     public static boolean isDumpingStaticArchive() {
 82         return (configStatus & IS_DUMPING_STATIC_ARCHIVE) != 0;
 83     }
 84 
















 85     private static native int getCDSConfigStatus();
 86     private static native void logLambdaFormInvoker(String line);
 87 
 88     /**
 89      * Initialize archived static fields in the given Class using archived
 90      * values from CDS dump time. Also initialize the classes of objects in
 91      * the archived graph referenced by those fields.
 92      *
 93      * Those static fields remain as uninitialized if there is no mapped CDS
 94      * java heap data or there is any error during initialization of the
 95      * object class in the archived graph.
 96      */
 97     public static native void initializeFromArchive(Class<?> c);
 98 
 99     /**
100      * Ensure that the native representation of all archived java.lang.Module objects
101      * are properly restored.
102      */
103     public static native void defineArchivedModules(ClassLoader platformLoader, ClassLoader systemLoader);
104 

110     public static native long getRandomSeedForDumping();
111 
112     /**
113      * log lambda form invoker holder, name and method type
114      */
115     public static void logLambdaFormInvoker(String prefix, String holder, String name, String type) {
116         if (isLoggingLambdaFormInvokers()) {
117             logLambdaFormInvoker(prefix + " " + holder + " " + name + " " + type);
118         }
119     }
120 
121     /**
122       * log species
123       */
124     public static void logSpeciesType(String prefix, String cn) {
125         if (isLoggingLambdaFormInvokers()) {
126             logLambdaFormInvoker(prefix + " " + cn);
127         }
128     }
129 









130     static final String DIRECT_HOLDER_CLASS_NAME  = "java.lang.invoke.DirectMethodHandle$Holder";
131     static final String DELEGATING_HOLDER_CLASS_NAME = "java.lang.invoke.DelegatingMethodHandle$Holder";
132     static final String BASIC_FORMS_HOLDER_CLASS_NAME = "java.lang.invoke.LambdaForm$Holder";
133     static final String INVOKERS_HOLDER_CLASS_NAME = "java.lang.invoke.Invokers$Holder";
134 
135     private static boolean isValidHolderName(String name) {
136         return name.equals(DIRECT_HOLDER_CLASS_NAME)      ||
137                name.equals(DELEGATING_HOLDER_CLASS_NAME)  ||
138                name.equals(BASIC_FORMS_HOLDER_CLASS_NAME) ||
139                name.equals(INVOKERS_HOLDER_CLASS_NAME);
140     }
141 
142     private static boolean isBasicTypeChar(char c) {
143          return "LIJFDV".indexOf(c) >= 0;
144     }
145 
146     private static boolean isValidMethodType(String type) {
147         String[] typeParts = type.split("_");
148         // check return type (second part)
149         if (typeParts.length != 2 || typeParts[1].length() != 1

456 
457             if (name.equals(currentClassName)) {
458                 // Note: the following call will call back to <code>this.findClass(name)</code> to
459                 // resolve the super types of the named class.
460                 return super.findClass(name);
461             }
462             if (name.equals(currentSuperClass.getName())) {
463                 return currentSuperClass;
464             }
465             if (currentInterfaces != null) {
466                 for (Class<?> c : currentInterfaces) {
467                     if (name.equals(c.getName())) {
468                         return c;
469                     }
470                 }
471             }
472 
473             throw new ClassNotFoundException(name);
474         }
475     }
















































476 }

 35 import java.net.URLClassLoader;
 36 import java.nio.file.InvalidPathException;
 37 import java.nio.file.Path;
 38 import java.util.Arrays;
 39 import java.util.ArrayList;
 40 import java.util.List;
 41 import java.util.Map;
 42 import java.util.Objects;
 43 import java.util.stream.Stream;
 44 
 45 import jdk.internal.access.SharedSecrets;
 46 import jdk.internal.util.StaticProperty;
 47 
 48 public class CDS {
 49     // Must be in sync with cdsConfig.hpp
 50     private static final int IS_DUMPING_ARCHIVE              = 1 << 0;
 51     private static final int IS_DUMPING_METHOD_HANDLES       = 1 << 1;
 52     private static final int IS_DUMPING_STATIC_ARCHIVE       = 1 << 2;
 53     private static final int IS_LOGGING_LAMBDA_FORM_INVOKERS = 1 << 3;
 54     private static final int IS_USING_ARCHIVE                = 1 << 4;
 55     private static final int IS_DUMPING_HEAP                 = 1 << 5;
 56     private static final int IS_LOGGING_DYNAMIC_PROXIES      = 1 << 6;
 57     private static final int IS_DUMPING_PACKAGES             = 1 << 7;
 58     private static final int IS_DUMPING_PROTECTION_DOMAINS   = 1 << 8;
 59     private static final int configStatus = getCDSConfigStatus();
 60 
 61     /**
 62      * Should we log the use of lambda form invokers?
 63      */
 64     public static boolean isLoggingLambdaFormInvokers() {
 65         return (configStatus & IS_LOGGING_LAMBDA_FORM_INVOKERS) != 0;
 66     }
 67 
 68     /**
 69       * Is the VM writing to a (static or dynamic) CDS archive.
 70       */
 71     public static boolean isDumpingArchive() {
 72         return (configStatus & IS_DUMPING_ARCHIVE) != 0;
 73     }
 74 
 75     /**
 76       * Is the VM using at least one CDS archive?
 77       */
 78     public static boolean isUsingArchive() {
 79         return (configStatus & IS_USING_ARCHIVE) != 0;
 80     }
 81 
 82     /**
 83       * Is dumping static archive.
 84       */
 85     public static boolean isDumpingStaticArchive() {
 86         return (configStatus & IS_DUMPING_STATIC_ARCHIVE) != 0;
 87     }
 88 
 89     public static boolean isDumpingHeap() {
 90         return (configStatus & IS_DUMPING_HEAP) != 0;
 91     }
 92 
 93     public static boolean isLoggingDynamicProxies() {
 94         return (configStatus & IS_LOGGING_DYNAMIC_PROXIES) != 0;
 95     }
 96 
 97     public static boolean isDumpingPackages() {
 98         return (configStatus & IS_DUMPING_PACKAGES) != 0;
 99     }
100 
101     public static boolean isDumpingProtectionDomains() {
102         return (configStatus & IS_DUMPING_PROTECTION_DOMAINS) != 0;
103     }
104 
105     private static native int getCDSConfigStatus();
106     private static native void logLambdaFormInvoker(String line);
107 
108     /**
109      * Initialize archived static fields in the given Class using archived
110      * values from CDS dump time. Also initialize the classes of objects in
111      * the archived graph referenced by those fields.
112      *
113      * Those static fields remain as uninitialized if there is no mapped CDS
114      * java heap data or there is any error during initialization of the
115      * object class in the archived graph.
116      */
117     public static native void initializeFromArchive(Class<?> c);
118 
119     /**
120      * Ensure that the native representation of all archived java.lang.Module objects
121      * are properly restored.
122      */
123     public static native void defineArchivedModules(ClassLoader platformLoader, ClassLoader systemLoader);
124 

130     public static native long getRandomSeedForDumping();
131 
132     /**
133      * log lambda form invoker holder, name and method type
134      */
135     public static void logLambdaFormInvoker(String prefix, String holder, String name, String type) {
136         if (isLoggingLambdaFormInvokers()) {
137             logLambdaFormInvoker(prefix + " " + holder + " " + name + " " + type);
138         }
139     }
140 
141     /**
142       * log species
143       */
144     public static void logSpeciesType(String prefix, String cn) {
145         if (isLoggingLambdaFormInvokers()) {
146             logLambdaFormInvoker(prefix + " " + cn);
147         }
148     }
149 
150     public static void logDynamicProxy(ClassLoader loader, String proxyName,
151                                        Class<?>[] interfaces, int accessFlags) {
152         Objects.requireNonNull(proxyName);
153         Objects.requireNonNull(interfaces);
154         logDynamicProxy0(loader, proxyName, interfaces, accessFlags);
155     }
156     private static native void logDynamicProxy0(ClassLoader loader, String proxyName,
157                                                 Class<?>[] interfaces, int accessFlags);
158 
159     static final String DIRECT_HOLDER_CLASS_NAME  = "java.lang.invoke.DirectMethodHandle$Holder";
160     static final String DELEGATING_HOLDER_CLASS_NAME = "java.lang.invoke.DelegatingMethodHandle$Holder";
161     static final String BASIC_FORMS_HOLDER_CLASS_NAME = "java.lang.invoke.LambdaForm$Holder";
162     static final String INVOKERS_HOLDER_CLASS_NAME = "java.lang.invoke.Invokers$Holder";
163 
164     private static boolean isValidHolderName(String name) {
165         return name.equals(DIRECT_HOLDER_CLASS_NAME)      ||
166                name.equals(DELEGATING_HOLDER_CLASS_NAME)  ||
167                name.equals(BASIC_FORMS_HOLDER_CLASS_NAME) ||
168                name.equals(INVOKERS_HOLDER_CLASS_NAME);
169     }
170 
171     private static boolean isBasicTypeChar(char c) {
172          return "LIJFDV".indexOf(c) >= 0;
173     }
174 
175     private static boolean isValidMethodType(String type) {
176         String[] typeParts = type.split("_");
177         // check return type (second part)
178         if (typeParts.length != 2 || typeParts[1].length() != 1

485 
486             if (name.equals(currentClassName)) {
487                 // Note: the following call will call back to <code>this.findClass(name)</code> to
488                 // resolve the super types of the named class.
489                 return super.findClass(name);
490             }
491             if (name.equals(currentSuperClass.getName())) {
492                 return currentSuperClass;
493             }
494             if (currentInterfaces != null) {
495                 for (Class<?> c : currentInterfaces) {
496                     if (name.equals(c.getName())) {
497                         return c;
498                     }
499                 }
500             }
501 
502             throw new ClassNotFoundException(name);
503         }
504     }
505 
506     /**
507      * This class is used only by native JVM code to spawn a child JVM process to assemble
508      * the AOT cache. <code>args[]</code> are passed in the <code>JAVA_TOOL_OPTIONS</code>
509      * environment variable as described in
510      * https://docs.oracle.com/en/java/javase/24/docs/specs/jvmti.html#tooloptions
511      */
512     private static class ProcessLauncher {
513         static int execWithJavaToolOptions(String javaLauncher, String args[]) throws IOException, InterruptedException {
514             ProcessBuilder pb = new ProcessBuilder().inheritIO().command(javaLauncher);
515             StringBuilder sb = new StringBuilder();
516             String prefix = "";
517             for (String arg : args) {
518                 sb.append(prefix);
519 
520                 for (int i = 0; i < arg.length(); i++) {
521                     char c = arg.charAt(i);
522                     if (c == '"' || Character.isWhitespace(c)) {
523                         sb.append('\'');
524                         sb.append(c);
525                         sb.append('\'');
526                     } else if (c == '\'') {
527                         sb.append('"');
528                         sb.append(c);
529                         sb.append('"');
530                     } else {
531                         sb.append(c);
532                     }
533                 }
534 
535                 prefix = " ";
536             }
537 
538             Map<String, String> env = pb.environment();
539             env.put("JAVA_TOOL_OPTIONS", sb.toString());
540             env.remove("_JAVA_OPTIONS");
541             env.remove("CLASSPATH");
542             Process process = pb.start();
543             return process.waitFor();
544         }
545     }
546 
547     /**
548      * This class is to ensure that the dynamic CDS archive contains at least one class, so we can avoid
549      * error handling for the degenerative case where the dynamic archive is completely empty (which doesn't
550      * happen for realistic applications).
551      */
552     private static class DummyForDynamicArchive {}
553 }
< prev index next >