1 /*
2 * Copyright (c) 2005, 2025, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.vm;
26
27 import jdk.internal.misc.Unsafe;
28 import jdk.internal.misc.VM;
29 import jdk.internal.access.SharedSecrets;
30 import jdk.internal.access.JavaLangAccess;
31 import jdk.internal.reflect.ConstantPool;
32 import sun.reflect.annotation.AnnotationParser;
33 import sun.reflect.annotation.AnnotationSupport;
34 import sun.reflect.annotation.AnnotationType;
35
36 import java.io.ByteArrayInputStream;
37 import java.io.ByteArrayOutputStream;
38 import java.io.DataInputStream;
39 import java.io.DataOutputStream;
40 import java.io.IOException;
41 import java.lang.annotation.Annotation;
42 import java.lang.annotation.IncompleteAnnotationException;
43 import java.nio.charset.StandardCharsets;
44 import java.util.Collection;
45 import java.util.LinkedHashMap;
46 import java.util.Map;
47 import java.util.Properties;
48 import java.util.Set;
49 import java.util.List;
50
51 /*
52 * Support class used by JVMCI, JVMTI and VM attach mechanism.
53 */
54 public class VMSupport {
55
56 private static final Unsafe U = Unsafe.getUnsafe();
57 private static Properties agentProps = null;
58
59 /**
60 * Returns the agent properties.
61 */
62 public static synchronized Properties getAgentProperties() {
63 if (agentProps == null) {
64 agentProps = new Properties();
65 initAgentProperties(agentProps);
66 }
67 return agentProps;
68 }
69 private static native Properties initAgentProperties(Properties props);
70
71 /**
72 * Writes the given properties list to a byte array and return it. The stream written
73 * to the byte array is ISO 8859-1 encoded.
74 */
75 private static byte[] serializePropertiesToByteArray(Properties p) throws IOException {
76 ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
99 }
100
101 public static byte[] serializeSecurityPropertiesToByteArray() throws IOException {
102 Properties p = SharedSecrets.getJavaSecurityPropertiesAccess().getCurrentProperties();
103 return serializePropertiesToByteArray(onlyStrings(p));
104 }
105
106 public static byte[] serializeAgentPropertiesToByteArray() throws IOException {
107 return serializePropertiesToByteArray(onlyStrings(getAgentProperties()));
108 }
109
110 /*
111 * Return the temporary directory that the VM uses for the attach
112 * and perf data files.
113 *
114 * It is important that this directory is well-known and the
115 * same for all VM instances. It cannot be affected by configuration
116 * variables such as java.io.tmpdir.
117 */
118 public static native String getVMTemporaryDirectory();
119
120 /**
121 * Decodes the exception described by {@code format} and {@code buffer} and throws it.
122 *
123 * @param format specifies how to interpret {@code buffer}:
124 * <pre>
125 * 0: {@code buffer} was created by {@link #encodeThrowable}
126 * 1: native memory for {@code buffer} could not be allocated
127 * 2: an OutOfMemoryError was thrown while encoding the exception
128 * 3: some other problem occured while encoding the exception. If {@code buffer != 0},
129 * it contains a {@code struct { u4 len; char[len] desc}} where {@code desc} describes the problem
130 * 4: an OutOfMemoryError thrown from within VM code on a
131 * thread that cannot call Java (OOME has no stack trace)
132 * </pre>
133 * @param buffer encoded info about the exception to throw (depends on {@code format})
134 * @param inJVMHeap [@code true} if executing in the JVM heap, {@code false} otherwise
135 * @param debug specifies whether debug stack traces should be enabled in case of translation failure
136 */
137 public static void decodeAndThrowThrowable(int format, long buffer, boolean inJVMHeap, boolean debug) throws Throwable {
138 if (format != 0) {
139 if (format == 4) {
140 throw new TranslatedException(new OutOfMemoryError("in VM code and current thread cannot call Java"));
141 }
142 String context = String.format("while encoding an exception to translate it %s the JVM heap",
143 inJVMHeap ? "to" : "from");
144 if (format == 1) {
145 throw new InternalError("native buffer could not be allocated " + context);
146 }
147 if (format == 2) {
148 throw new OutOfMemoryError(context);
149 }
150 if (format == 3 && buffer != 0L) {
151 byte[] bytes = bufferToBytes(buffer);
152 throw new InternalError("unexpected problem occurred " + context + ": " + new String(bytes, StandardCharsets.UTF_8));
153 }
154 throw new InternalError("unexpected problem occurred " + context);
155 }
156 throw TranslatedException.decodeThrowable(bufferToBytes(buffer), debug);
157 }
158
159 private static byte[] bufferToBytes(long buffer) {
160 if (buffer == 0) {
161 return null;
162 }
163 int len = U.getInt(buffer);
164 byte[] bytes = new byte[len];
165 U.copyMemory(null, buffer + 4, bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, len);
166 return bytes;
167 }
168
169 /**
170 * If {@code bufferSize} is large enough, encodes {@code throwable} into a byte array and writes
171 * it to {@code buffer}. The encoding in {@code buffer} can be decoded by
172 * {@link #decodeAndThrowThrowable}.
173 *
174 * @param throwable the exception to encode
175 * @param buffer a native byte buffer
176 * @param bufferSize the size of {@code buffer} in bytes
177 * @return the number of bytes written into {@code buffer} if {@code bufferSize} is large
178 * enough, otherwise {@code -N} where {@code N} is the value {@code bufferSize} needs to
179 * be to fit the encoding
180 */
181 public static int encodeThrowable(Throwable throwable, long buffer, int bufferSize) {
182 byte[] encoding = TranslatedException.encodeThrowable(throwable);
183 int requiredSize = 4 + encoding.length;
184 if (bufferSize < requiredSize) {
185 return -requiredSize;
186 }
187 U.putInt(buffer, encoding.length);
188 U.copyMemory(encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, buffer + 4, encoding.length);
189 return requiredSize;
190 }
191
192 /**
193 * Parses {@code rawAnnotations} into a list of {@link Annotation}s and then
194 * serializes them to a byte array with {@link #encodeAnnotations(Collection)}.
195 */
196 public static byte[] encodeAnnotations(byte[] rawAnnotations,
197 Class<?> declaringClass,
198 ConstantPool cp,
199 boolean forClass,
200 Class<? extends Annotation>[] selectAnnotationClasses)
201 {
202 for (Class<?> c : selectAnnotationClasses) {
203 if (!c.isAnnotation()) {
204 throw new IllegalArgumentException(c + " is not an annotation interface");
205 }
206 }
207 Map<Class<? extends Annotation>, Annotation> annotations =
208 AnnotationParser.parseSelectAnnotations(rawAnnotations, cp, declaringClass, selectAnnotationClasses);
209 if (forClass && annotations.size() != selectAnnotationClasses.length) {
210 Class<?> superClass = declaringClass.getSuperclass();
211 nextSuperClass:
212 while (superClass != null) {
213 JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
214 Map<Class<? extends Annotation>, Annotation> superAnnotations =
215 AnnotationParser.parseSelectAnnotations(
216 jla.getRawClassAnnotations(superClass),
217 jla.getConstantPool(superClass),
218 superClass,
219 selectAnnotationClasses);
220
221 for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) {
222 Class<? extends Annotation> annotationClass = e.getKey();
223 if (!annotations.containsKey(annotationClass) && AnnotationType.getInstance(annotationClass).isInherited()) {
224 if (annotations.isEmpty()) {
225 // An empty map might be unmodifiable (e.g. Collections.emptyMap()).
226 annotations = new LinkedHashMap<Class<? extends Annotation>, Annotation>();
227 }
228 annotations.put(annotationClass, e.getValue());
229 if (annotations.size() == selectAnnotationClasses.length) {
230 break nextSuperClass;
231 }
232 }
233 }
234 superClass = superClass.getSuperclass();
235 }
236 }
237 return encodeAnnotations(annotations.values());
238 }
239
240 /**
241 * Encodes annotations to a byte array. The byte array can be decoded with {@link #decodeAnnotations(byte[], AnnotationDecoder)}.
242 */
243 public static byte[] encodeAnnotations(Collection<Annotation> annotations) {
244 try {
245 ByteArrayOutputStream baos = new ByteArrayOutputStream(128);
246 try (DataOutputStream dos = new DataOutputStream(baos)) {
247 writeLength(dos, annotations.size());
248 for (Annotation a : annotations) {
249 encodeAnnotation(dos, a);
250 }
251 }
252 return baos.toByteArray();
253 } catch (Exception e) {
254 throw new InternalError(e);
255 }
256 }
257
258 private static void encodeAnnotation(DataOutputStream dos, Annotation a) throws Exception {
259 Class<? extends Annotation> type = a.annotationType();
260 Map<String, Object> values = AnnotationSupport.memberValues(a);
261 dos.writeUTF(type.getName());
262 writeLength(dos, values.size());
263 for (Map.Entry<String, Object> e : values.entrySet()) {
264 Object value = e.getValue();
265 if (value == null) {
266 // IncompleteAnnotationException
267 dos.writeByte('x');
268 dos.writeUTF(new IncompleteAnnotationException(type, e.getKey()).toString());
269 continue;
270 }
271 Class<?> valueType = value.getClass();
272 dos.writeUTF(e.getKey());
273 if (valueType == Byte.class) {
274 dos.writeByte('B');
275 dos.writeByte((byte) value);
276 } else if (valueType == Character.class) {
277 dos.writeByte('C');
278 dos.writeChar((char) value);
279 } else if (valueType == Double.class) {
280 dos.writeByte('D');
281 dos.writeDouble((double) value);
282 } else if (valueType == Float.class) {
283 dos.writeByte('F');
284 dos.writeFloat((float) value);
285 } else if (valueType == Integer.class) {
286 dos.writeByte('I');
287 dos.writeInt((int) value);
288 } else if (valueType == Long.class) {
289 dos.writeByte('J');
290 dos.writeLong((long) value);
291 } else if (valueType == Short.class) {
292 dos.writeByte('S');
293 dos.writeShort((short) value);
294 } else if (valueType == Boolean.class) {
295 dos.writeByte('Z');
296 dos.writeBoolean((boolean) value);
297 } else if (valueType == String.class) {
298 dos.writeByte('s');
299 dos.writeUTF((String) value);
300 } else if (valueType == Class.class) {
301 dos.writeByte('c');
302 dos.writeUTF(((Class<?>) value).getName());
303 } else if (valueType.isEnum()) {
304 dos.writeByte('e');
305 dos.writeUTF(valueType.getName());
306 dos.writeUTF(((Enum<?>) value).name());
307 } else if (value instanceof Annotation) {
308 dos.writeByte('@');
309 encodeAnnotation(dos, (Annotation) value);
310 } else if (valueType.isArray()) {
311 Class<?> componentType = valueType.getComponentType();
312 if (componentType == byte.class) {
313 byte[] array = (byte[]) value;
314 dos.writeByte('[');
315 dos.writeByte('B');
316 writeLength(dos, array.length);
317 dos.write(array);
318 } else if (componentType == char.class) {
319 char[] array = (char[]) value;
320 dos.writeByte('[');
321 dos.writeByte('C');
322 writeLength(dos, array.length);
323 for (char c : array) {
324 dos.writeChar(c);
325 }
326 } else if (componentType == double.class) {
327 double[] array = (double[]) value;
328 dos.writeByte('[');
329 dos.writeByte('D');
330 writeLength(dos, array.length);
331 for (double v : array) {
332 dos.writeDouble(v);
333 }
334 } else if (componentType == float.class) {
335 float[] array = (float[]) value;
336 dos.writeByte('[');
337 dos.writeByte('F');
338 writeLength(dos, array.length);
339 for (float v : array) {
340 dos.writeFloat(v);
341 }
342 } else if (componentType == int.class) {
343 int[] array = (int[]) value;
344 dos.writeByte('[');
345 dos.writeByte('I');
346 writeLength(dos, array.length);
347 for (int j : array) {
348 dos.writeInt(j);
349 }
350 } else if (componentType == long.class) {
351 long[] array = (long[]) value;
352 dos.writeByte('[');
353 dos.writeByte('J');
354 writeLength(dos, array.length);
355 for (long l : array) {
356 dos.writeLong(l);
357 }
358 } else if (componentType == short.class) {
359 short[] array = (short[]) value;
360 dos.writeByte('[');
361 dos.writeByte('S');
362 writeLength(dos, array.length);
363 for (short item : array) {
364 dos.writeShort(item);
365 }
366 } else if (componentType == boolean.class) {
367 boolean[] array = (boolean[]) value;
368 dos.writeByte('[');
369 dos.writeByte('Z');
370 writeLength(dos, array.length);
371 for (boolean b : array) {
372 dos.writeBoolean(b);
373 }
374 } else if (componentType == String.class) {
375 String[] array = (String[]) value;
376 dos.writeByte('[');
377 dos.writeByte('s');
378 writeLength(dos, array.length);
379 for (String s : array) {
380 dos.writeUTF(s);
381 }
382 } else if (componentType == Class.class) {
383 Class<?>[] array = (Class<?>[]) value;
384 dos.writeByte('[');
385 dos.writeByte('c');
386 writeLength(dos, array.length);
387 for (Class<?> aClass : array) {
388 dos.writeUTF(aClass.getName());
389 }
390 } else if (componentType.isEnum()) {
391 Enum<?>[] array = (Enum<?>[]) value;
392 dos.writeByte('[');
393 dos.writeByte('e');
394 dos.writeUTF(componentType.getName());
395 writeLength(dos, array.length);
396 for (Enum<?> anEnum : array) {
397 dos.writeUTF(anEnum.name());
398 }
399 } else if (componentType.isAnnotation()) {
400 Annotation[] array = (Annotation[]) value;
401 dos.writeByte('[');
402 dos.writeByte('@');
403 writeLength(dos, array.length);
404 for (Annotation annotation : array) {
405 encodeAnnotation(dos, annotation);
406 }
407 } else {
408 dos.writeByte('x');
409 dos.writeUTF(value.toString());
410 }
411
412 } else {
413 dos.writeByte('x');
414 dos.writeUTF(value.toString());
415 }
416 }
417 }
418
419 /**
420 * Helper for {@link #decodeAnnotations(byte[], AnnotationDecoder)} to convert a byte
421 * array (ostensibly produced by {@link VMSupport#encodeAnnotations}) into objects.
422 *
423 * @param <T> type to which a type name is {@linkplain #resolveType(String) resolved}
424 * @param <A> type of the object representing a decoded annotation
425 * @param <E> type of the object representing a decoded enum constant
426 * @param <X> type of the object representing a decoded error
427 */
428 public interface AnnotationDecoder<T, A, E, X> {
429 /**
430 * Resolves a name in {@link Class#getName()} format to an object of type {@code T}.
431 */
432 T resolveType(String name);
433
434 /**
435 * Creates an object representing a decoded annotation.
436 *
437 * @param type the annotation interface of the annotation
438 * @param elements elements of the annotation
439 */
440 A newAnnotation(T type, Map.Entry<String, Object>[] elements);
441
442 /**
443 * Creates an object representing a decoded enum constant.
444 *
445 * @param enumType the enum type
446 * @param name the name of the enum constant
447 */
448 E newEnumValue(T enumType, String name);
449
450 /**
451 * Creates an object representing a decoded error value.
452 *
453 * @param description of the error
454 */
455 X newErrorValue(String description);
456 }
457
458 /**
459 * Decodes annotations serialized in {@code encoded} to objects.
460 *
461 * @param <T> type to which a type name is resolved
462 * @param <A> type of the object representing a decoded annotation
463 * @param <E> type of the object representing a decoded enum constant
464 * @param <X> type of the object representing a decoded error
465 * @return an immutable list of {@code A} objects
466 */
467 @SuppressWarnings("unchecked")
468 public static <T, A, E, X> List<A> decodeAnnotations(byte[] encoded, AnnotationDecoder<T, A, E, X> decoder) {
469 try {
470 ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
471 DataInputStream dis = new DataInputStream(bais);
472 return (List<A>) readArray(dis, () -> decodeAnnotation(dis, decoder));
473 } catch (Exception e) {
474 throw new InternalError(e);
475 }
476 }
477
478 @SuppressWarnings({"rawtypes", "unchecked"})
479 private static <T, A, E, X> A decodeAnnotation(DataInputStream dis, AnnotationDecoder<T, A, E, X> decoder) throws IOException {
480 String typeName = dis.readUTF();
481 T type = decoder.resolveType(typeName);
482 int n = readLength(dis);
483 Map.Entry[] elements = new Map.Entry[n];
484 for (int i = 0; i < n; i++) {
485 String name = dis.readUTF();
486 byte tag = dis.readByte();
487 elements[i] = Map.entry(name, switch (tag) {
488 case 'B' -> dis.readByte();
489 case 'C' -> dis.readChar();
490 case 'D' -> dis.readDouble();
491 case 'F' -> dis.readFloat();
492 case 'I' -> dis.readInt();
493 case 'J' -> dis.readLong();
494 case 'S' -> dis.readShort();
495 case 'Z' -> dis.readBoolean();
496 case 's' -> dis.readUTF();
497 case 'c' -> decoder.resolveType(dis.readUTF());
498 case 'e' -> decoder.newEnumValue(decoder.resolveType(dis.readUTF()), dis.readUTF());
499 case '@' -> decodeAnnotation(dis, decoder);
500 case '[' -> decodeArray(dis, decoder);
501 case 'x' -> decoder.newErrorValue(dis.readUTF());
502 default -> throw new InternalError("Unsupported tag: " + tag);
503 });
504 }
505 return decoder.newAnnotation(type, (Map.Entry<String, Object>[]) elements);
506 }
507 @FunctionalInterface
508 interface IOReader {
509 Object read() throws IOException;
510 }
511
512 private static <T, A, E, X> Object decodeArray(DataInputStream dis, AnnotationDecoder<T, A, E, X> decoder) throws IOException {
513 byte componentTag = dis.readByte();
514 return switch (componentTag) {
515 case 'B' -> readArray(dis, dis::readByte);
516 case 'C' -> readArray(dis, dis::readChar);
517 case 'D' -> readArray(dis, dis::readDouble);
518 case 'F' -> readArray(dis, dis::readFloat);
519 case 'I' -> readArray(dis, dis::readInt);
520 case 'J' -> readArray(dis, dis::readLong);
521 case 'S' -> readArray(dis, dis::readShort);
522 case 'Z' -> readArray(dis, dis::readBoolean);
523 case 's' -> readArray(dis, dis::readUTF);
524 case 'c' -> readArray(dis, () -> readClass(dis, decoder));
525 case 'e' -> {
526 T enumType = decoder.resolveType(dis.readUTF());
527 yield readArray(dis, () -> readEnum(dis, decoder, enumType));
528 }
529 case '@' -> readArray(dis, () -> decodeAnnotation(dis, decoder));
530 default -> throw new InternalError("Unsupported component tag: " + componentTag);
531 };
532 }
533
534 /**
535 * Reads an enum encoded at the current read position of {@code dis} and
536 * returns it as an object of type {@code E}.
537 */
538 private static <T, A, E, X> E readEnum(DataInputStream dis, AnnotationDecoder<T, A, E, X> decoder, T enumType) throws IOException {
539 return decoder.newEnumValue(enumType, dis.readUTF());
540 }
541
542 /**
543 * Reads a class encoded at the current read position of {@code dis} and
544 * returns it as an object of type {@code T}.
545 */
546 private static <T, A, E, X> T readClass(DataInputStream dis, AnnotationDecoder<T, A, E, X> decoder) throws IOException {
547 return decoder.resolveType(dis.readUTF());
548 }
549
550 /**
551 * Reads an array encoded at the current read position of {@code dis} and
552 * returns it in an immutable list.
553 *
554 * @param reader reads array elements from {@code dis}
555 * @return an immutable list of {@code A} objects
556 */
557 private static List<Object> readArray(DataInputStream dis, IOReader reader) throws IOException {
558 Object[] array = new Object[readLength(dis)];
559 for (int i = 0; i < array.length; i++) {
560 array[i] = reader.read();
561 }
562 return List.of(array);
563 }
564
565 /**
566 * Encodes {@code length} in 1 byte if it is less than 128.
567 */
568 private static void writeLength(DataOutputStream dos, int length) throws IOException {
569 if (length < 0) {
570 throw new NegativeArraySizeException();
571 } else if (length <= 127) {
572 dos.writeByte((byte) (0x80 | length));
573 } else {
574 dos.writeInt(length);
575 }
576 }
577
578 private static int readLength(DataInputStream dis) throws IOException {
579 int ch1 = dis.readByte();
580 int length;
581 if (ch1 < 0) {
582 length = ch1 & 0x7F;
583 } else {
584 int ch2 = dis.read();
585 int ch3 = dis.read();
586 int ch4 = dis.read();
587 length = (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0);
588 }
589 return length;
590 }
591 }
|
1 /*
2 * Copyright (c) 2005, 2026, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.vm;
26
27 import jdk.internal.access.SharedSecrets;
28
29 import java.io.ByteArrayOutputStream;
30 import java.io.IOException;
31 import java.util.Properties;
32 import java.util.Set;
33
34 /*
35 * Support class used by JVMTI and VM attach mechanism.
36 */
37 public class VMSupport {
38
39 private static Properties agentProps = null;
40
41 /**
42 * Returns the agent properties.
43 */
44 public static synchronized Properties getAgentProperties() {
45 if (agentProps == null) {
46 agentProps = new Properties();
47 initAgentProperties(agentProps);
48 }
49 return agentProps;
50 }
51 private static native Properties initAgentProperties(Properties props);
52
53 /**
54 * Writes the given properties list to a byte array and return it. The stream written
55 * to the byte array is ISO 8859-1 encoded.
56 */
57 private static byte[] serializePropertiesToByteArray(Properties p) throws IOException {
58 ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
81 }
82
83 public static byte[] serializeSecurityPropertiesToByteArray() throws IOException {
84 Properties p = SharedSecrets.getJavaSecurityPropertiesAccess().getCurrentProperties();
85 return serializePropertiesToByteArray(onlyStrings(p));
86 }
87
88 public static byte[] serializeAgentPropertiesToByteArray() throws IOException {
89 return serializePropertiesToByteArray(onlyStrings(getAgentProperties()));
90 }
91
92 /*
93 * Return the temporary directory that the VM uses for the attach
94 * and perf data files.
95 *
96 * It is important that this directory is well-known and the
97 * same for all VM instances. It cannot be affected by configuration
98 * variables such as java.io.tmpdir.
99 */
100 public static native String getVMTemporaryDirectory();
101 }
|