< prev index next >

src/java.base/share/classes/jdk/internal/vm/VMSupport.java

Print this page

  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 }
< prev index next >