35 import java.nio.file.Path;
36 import java.util.Arrays;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Objects;
42 import java.util.jar.JarFile;
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
532 } else if (c == '\'') {
533 sb.append('"');
534 sb.append(c);
535 sb.append('"');
536 } else {
537 sb.append(c);
538 }
539 }
540
541 prefix = " ";
542 }
543
544 Map<String, String> env = pb.environment();
545 env.put("JAVA_TOOL_OPTIONS", sb.toString());
546 env.remove("_JAVA_OPTIONS");
547 env.remove("CLASSPATH");
548 Process process = pb.start();
549 return process.waitFor();
550 }
551 }
552 }
|
35 import java.nio.file.Path;
36 import java.util.Arrays;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Objects;
42 import java.util.jar.JarFile;
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
561 } else if (c == '\'') {
562 sb.append('"');
563 sb.append(c);
564 sb.append('"');
565 } else {
566 sb.append(c);
567 }
568 }
569
570 prefix = " ";
571 }
572
573 Map<String, String> env = pb.environment();
574 env.put("JAVA_TOOL_OPTIONS", sb.toString());
575 env.remove("_JAVA_OPTIONS");
576 env.remove("CLASSPATH");
577 Process process = pb.start();
578 return process.waitFor();
579 }
580 }
581
582 /**
583 * This class is to ensure that the dynamic CDS archive contains at least one class, so we can avoid
584 * error handling for the degenerative case where the dynamic archive is completely empty (which doesn't
585 * happen for realistic applications).
586 */
587 private static class DummyForDynamicArchive {}
588 }
|