281 } |
281 } |
282 return ClassLoader.getSystemClassLoader(); |
282 return ClassLoader.getSystemClassLoader(); |
283 } |
283 } |
284 |
284 |
285 /** |
285 /** |
|
286 * A Java {@code char} has a maximal UTF8 length of 3. |
|
287 */ |
|
288 private static final int MAX_UNICODE_IN_UTF8_LENGTH = 3; |
|
289 |
|
290 /** |
|
291 * {@link DataOutputStream#writeUTF(String)} only supports values whose UTF8 encoding length is |
|
292 * less than 65535. |
|
293 */ |
|
294 private static final int MAX_UTF8_PROPERTY_STRING_LENGTH = 65535 / MAX_UNICODE_IN_UTF8_LENGTH; |
|
295 |
|
296 /** |
286 * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for |
297 * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for |
287 * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial |
298 * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial |
288 * properties in the JVMCI shared library. |
299 * properties in the JVMCI shared library. |
289 */ |
300 */ |
290 @VMEntryPoint |
301 @VMEntryPoint |
291 private static byte[] serializeSavedProperties() throws IOException { |
302 private static byte[] serializeSavedProperties() throws IOException { |
292 if (IS_IN_NATIVE_IMAGE) { |
303 if (IS_IN_NATIVE_IMAGE) { |
293 throw new InternalError("Can only serialize saved properties in HotSpot runtime"); |
304 throw new InternalError("Can only serialize saved properties in HotSpot runtime"); |
294 } |
305 } |
295 Map<String, String> props = Services.getSavedProperties(); |
306 return serializeProperties(Services.getSavedProperties()); |
296 |
307 } |
|
308 |
|
309 private static byte[] serializeProperties(Map<String, String> props) throws IOException { |
297 // Compute size of output on the assumption that |
310 // Compute size of output on the assumption that |
298 // all system properties have ASCII names and values |
311 // all system properties have ASCII names and values |
299 int estimate = 4; |
312 int estimate = 4 + 4; |
|
313 int nonUtf8Props = 0; |
300 for (Map.Entry<String, String> e : props.entrySet()) { |
314 for (Map.Entry<String, String> e : props.entrySet()) { |
301 String name = e.getKey(); |
315 String name = e.getKey(); |
302 String value = e.getValue(); |
316 String value = e.getValue(); |
303 estimate += (2 + (name.length())) + (2 + (value.length())); |
317 estimate += (2 + (name.length())) + (2 + (value.length())); |
|
318 if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) { |
|
319 nonUtf8Props++; |
|
320 } |
304 } |
321 } |
305 |
322 |
306 ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate); |
323 ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate); |
307 DataOutputStream out = new DataOutputStream(baos); |
324 DataOutputStream out = new DataOutputStream(baos); |
308 out.writeInt(props.size()); |
325 out.writeInt(props.size() - nonUtf8Props); |
|
326 out.writeInt(nonUtf8Props); |
309 for (Map.Entry<String, String> e : props.entrySet()) { |
327 for (Map.Entry<String, String> e : props.entrySet()) { |
310 String name = e.getKey(); |
328 String name = e.getKey(); |
311 String value = e.getValue(); |
329 String value = e.getValue(); |
312 out.writeUTF(name); |
330 if (name.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH && value.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH) { |
313 out.writeUTF(value); |
331 out.writeUTF(name); |
|
332 out.writeUTF(value); |
|
333 } |
|
334 } |
|
335 if (nonUtf8Props != 0) { |
|
336 for (Map.Entry<String, String> e : props.entrySet()) { |
|
337 String name = e.getKey(); |
|
338 String value = e.getValue(); |
|
339 if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) { |
|
340 byte[] utf8Name = name.getBytes("UTF-8"); |
|
341 byte[] utf8Value = value.getBytes("UTF-8"); |
|
342 out.writeInt(utf8Name.length); |
|
343 out.write(utf8Name); |
|
344 out.writeInt(utf8Value.length); |
|
345 out.write(utf8Value); |
|
346 } |
|
347 } |
314 } |
348 } |
315 return baos.toByteArray(); |
349 return baos.toByteArray(); |
316 } |
350 } |
317 |
351 |
318 /** |
352 /** |
323 @VMEntryPoint |
357 @VMEntryPoint |
324 private static void initializeSavedProperties(byte[] serializedProperties) throws IOException { |
358 private static void initializeSavedProperties(byte[] serializedProperties) throws IOException { |
325 if (!IS_IN_NATIVE_IMAGE) { |
359 if (!IS_IN_NATIVE_IMAGE) { |
326 throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime"); |
360 throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime"); |
327 } |
361 } |
|
362 savedProperties = Collections.unmodifiableMap(deserializeProperties(serializedProperties)); |
|
363 } |
|
364 |
|
365 private static Map<String, String> deserializeProperties(byte[] serializedProperties) throws IOException { |
328 DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties)); |
366 DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties)); |
329 Map<String, String> props = new HashMap<>(in.readInt()); |
367 int utf8Props = in.readInt(); |
|
368 int nonUtf8Props = in.readInt(); |
|
369 Map<String, String> props = new HashMap<>(utf8Props + nonUtf8Props); |
|
370 int index = 0; |
330 while (in.available() != 0) { |
371 while (in.available() != 0) { |
331 String name = in.readUTF(); |
372 if (index < utf8Props) { |
332 String value = in.readUTF(); |
373 String name = in.readUTF(); |
333 props.put(name, value); |
374 String value = in.readUTF(); |
334 } |
375 props.put(name, value); |
335 savedProperties = Collections.unmodifiableMap(props); |
376 } else { |
|
377 int nameLen = in.readInt(); |
|
378 byte[] nameBytes = new byte[nameLen]; |
|
379 in.read(nameBytes); |
|
380 int valueLen = in.readInt(); |
|
381 byte[] valueBytes = new byte[valueLen]; |
|
382 in.read(valueBytes); |
|
383 String name = new String(nameBytes, "UTF-8"); |
|
384 String value = new String(valueBytes, "UTF-8"); |
|
385 props.put(name, value); |
|
386 } |
|
387 index++; |
|
388 } |
|
389 return props; |
336 } |
390 } |
337 } |
391 } |