< 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     public static boolean isSingleThreadVM() {
 86         return isDumpingStaticArchive();
 87     }
 88 
 89     private static native int getCDSConfigStatus();
 90     private static native void logLambdaFormInvoker(String line);
 91 
 92 
 93     // Used only when dumping static archive to keep weak references alive to
 94     // ensure that Soft/Weak Reference objects can be reliably archived.
 95     private static ArrayList<Object> keepAliveList;
 96 
 97     public static void keepAlive(Object s) {
 98         assert isSingleThreadVM(); // no need for synchronization
 99         assert isDumpingStaticArchive();
100         if (keepAliveList == null) {
101             keepAliveList = new ArrayList<>();
102         }
103         keepAliveList.add(s);
104     }

137     public static native long getRandomSeedForDumping();
138 
139     /**
140      * log lambda form invoker holder, name and method type
141      */
142     public static void logLambdaFormInvoker(String prefix, String holder, String name, String type) {
143         if (isLoggingLambdaFormInvokers()) {
144             logLambdaFormInvoker(prefix + " " + holder + " " + name + " " + type);
145         }
146     }
147 
148     /**
149       * log species
150       */
151     public static void logSpeciesType(String prefix, String cn) {
152         if (isLoggingLambdaFormInvokers()) {
153             logLambdaFormInvoker(prefix + " " + cn);
154         }
155     }
156 









157     static final String DIRECT_HOLDER_CLASS_NAME  = "java.lang.invoke.DirectMethodHandle$Holder";
158     static final String DELEGATING_HOLDER_CLASS_NAME = "java.lang.invoke.DelegatingMethodHandle$Holder";
159     static final String BASIC_FORMS_HOLDER_CLASS_NAME = "java.lang.invoke.LambdaForm$Holder";
160     static final String INVOKERS_HOLDER_CLASS_NAME = "java.lang.invoke.Invokers$Holder";
161 
162     private static boolean isValidHolderName(String name) {
163         return name.equals(DIRECT_HOLDER_CLASS_NAME)      ||
164                name.equals(DELEGATING_HOLDER_CLASS_NAME)  ||
165                name.equals(BASIC_FORMS_HOLDER_CLASS_NAME) ||
166                name.equals(INVOKERS_HOLDER_CLASS_NAME);
167     }
168 
169     private static boolean isBasicTypeChar(char c) {
170          return "LIJFDV".indexOf(c) >= 0;
171     }
172 
173     private static boolean isValidMethodType(String type) {
174         String[] typeParts = type.split("_");
175         // check return type (second part)
176         if (typeParts.length != 2 || typeParts[1].length() != 1

483 
484             if (name.equals(currentClassName)) {
485                 // Note: the following call will call back to <code>this.findClass(name)</code> to
486                 // resolve the super types of the named class.
487                 return super.findClass(name);
488             }
489             if (name.equals(currentSuperClass.getName())) {
490                 return currentSuperClass;
491             }
492             if (currentInterfaces != null) {
493                 for (Class<?> c : currentInterfaces) {
494                     if (name.equals(c.getName())) {
495                         return c;
496                     }
497                 }
498             }
499 
500             throw new ClassNotFoundException(name);
501         }
502     }
















































503 }

 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     public static boolean isSingleThreadVM() {
106         return isDumpingStaticArchive();
107     }
108 
109     private static native int getCDSConfigStatus();
110     private static native void logLambdaFormInvoker(String line);
111 
112 
113     // Used only when dumping static archive to keep weak references alive to
114     // ensure that Soft/Weak Reference objects can be reliably archived.
115     private static ArrayList<Object> keepAliveList;
116 
117     public static void keepAlive(Object s) {
118         assert isSingleThreadVM(); // no need for synchronization
119         assert isDumpingStaticArchive();
120         if (keepAliveList == null) {
121             keepAliveList = new ArrayList<>();
122         }
123         keepAliveList.add(s);
124     }

157     public static native long getRandomSeedForDumping();
158 
159     /**
160      * log lambda form invoker holder, name and method type
161      */
162     public static void logLambdaFormInvoker(String prefix, String holder, String name, String type) {
163         if (isLoggingLambdaFormInvokers()) {
164             logLambdaFormInvoker(prefix + " " + holder + " " + name + " " + type);
165         }
166     }
167 
168     /**
169       * log species
170       */
171     public static void logSpeciesType(String prefix, String cn) {
172         if (isLoggingLambdaFormInvokers()) {
173             logLambdaFormInvoker(prefix + " " + cn);
174         }
175     }
176 
177     public static void logDynamicProxy(ClassLoader loader, String proxyName,
178                                        Class<?>[] interfaces, int accessFlags) {
179         Objects.requireNonNull(proxyName);
180         Objects.requireNonNull(interfaces);
181         logDynamicProxy0(loader, proxyName, interfaces, accessFlags);
182     }
183     private static native void logDynamicProxy0(ClassLoader loader, String proxyName,
184                                                 Class<?>[] interfaces, int accessFlags);
185 
186     static final String DIRECT_HOLDER_CLASS_NAME  = "java.lang.invoke.DirectMethodHandle$Holder";
187     static final String DELEGATING_HOLDER_CLASS_NAME = "java.lang.invoke.DelegatingMethodHandle$Holder";
188     static final String BASIC_FORMS_HOLDER_CLASS_NAME = "java.lang.invoke.LambdaForm$Holder";
189     static final String INVOKERS_HOLDER_CLASS_NAME = "java.lang.invoke.Invokers$Holder";
190 
191     private static boolean isValidHolderName(String name) {
192         return name.equals(DIRECT_HOLDER_CLASS_NAME)      ||
193                name.equals(DELEGATING_HOLDER_CLASS_NAME)  ||
194                name.equals(BASIC_FORMS_HOLDER_CLASS_NAME) ||
195                name.equals(INVOKERS_HOLDER_CLASS_NAME);
196     }
197 
198     private static boolean isBasicTypeChar(char c) {
199          return "LIJFDV".indexOf(c) >= 0;
200     }
201 
202     private static boolean isValidMethodType(String type) {
203         String[] typeParts = type.split("_");
204         // check return type (second part)
205         if (typeParts.length != 2 || typeParts[1].length() != 1

512 
513             if (name.equals(currentClassName)) {
514                 // Note: the following call will call back to <code>this.findClass(name)</code> to
515                 // resolve the super types of the named class.
516                 return super.findClass(name);
517             }
518             if (name.equals(currentSuperClass.getName())) {
519                 return currentSuperClass;
520             }
521             if (currentInterfaces != null) {
522                 for (Class<?> c : currentInterfaces) {
523                     if (name.equals(c.getName())) {
524                         return c;
525                     }
526                 }
527             }
528 
529             throw new ClassNotFoundException(name);
530         }
531     }
532 
533     /**
534      * This class is used only by native JVM code to spawn a child JVM process to assemble
535      * the AOT cache. <code>args[]</code> are passed in the <code>JAVA_TOOL_OPTIONS</code>
536      * environment variable as described in
537      * https://docs.oracle.com/en/java/javase/24/docs/specs/jvmti.html#tooloptions
538      */
539     private static class ProcessLauncher {
540         static int execWithJavaToolOptions(String javaLauncher, String args[]) throws IOException, InterruptedException {
541             ProcessBuilder pb = new ProcessBuilder().inheritIO().command(javaLauncher);
542             StringBuilder sb = new StringBuilder();
543             String prefix = "";
544             for (String arg : args) {
545                 sb.append(prefix);
546 
547                 for (int i = 0; i < arg.length(); i++) {
548                     char c = arg.charAt(i);
549                     if (c == '"' || Character.isWhitespace(c)) {
550                         sb.append('\'');
551                         sb.append(c);
552                         sb.append('\'');
553                     } else if (c == '\'') {
554                         sb.append('"');
555                         sb.append(c);
556                         sb.append('"');
557                     } else {
558                         sb.append(c);
559                     }
560                 }
561 
562                 prefix = " ";
563             }
564 
565             Map<String, String> env = pb.environment();
566             env.put("JAVA_TOOL_OPTIONS", sb.toString());
567             env.remove("_JAVA_OPTIONS");
568             env.remove("CLASSPATH");
569             Process process = pb.start();
570             return process.waitFor();
571         }
572     }
573 
574     /**
575      * This class is to ensure that the dynamic CDS archive contains at least one class, so we can avoid
576      * error handling for the degenerative case where the dynamic archive is completely empty (which doesn't
577      * happen for realistic applications).
578      */
579     private static class DummyForDynamicArchive {}
580 }
< prev index next >