diff options
author | Adam Cozzette <acozzette@google.com> | 2017-12-01 10:05:19 -0800 |
---|---|---|
committer | Adam Cozzette <acozzette@google.com> | 2017-12-01 10:05:19 -0800 |
commit | 0ba8eea655a5e40d19ab95c773192b5d908c5a61 (patch) | |
tree | 4c2c97ade1ab197d361c146bacae5adde55986bf /java/core/src/main/java/com/google/protobuf/UnsafeUtil.java | |
parent | 92a7e778e7394386f413cec28d67a07630f784b1 (diff) | |
parent | a711e3d5b4ee1dd7f9d21197dca8432a5819a64e (diff) | |
download | protobuf-0ba8eea655a5e40d19ab95c773192b5d908c5a61.tar.gz protobuf-0ba8eea655a5e40d19ab95c773192b5d908c5a61.tar.bz2 protobuf-0ba8eea655a5e40d19ab95c773192b5d908c5a61.zip |
Merge branch 'master' into down-integrate
Diffstat (limited to 'java/core/src/main/java/com/google/protobuf/UnsafeUtil.java')
-rw-r--r-- | java/core/src/main/java/com/google/protobuf/UnsafeUtil.java | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java index 98c93b90..b09ff673 100644 --- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java +++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java @@ -33,7 +33,6 @@ package com.google.protobuf; import java.lang.reflect.Field; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.logging.Level; @@ -72,6 +71,8 @@ final class UnsafeUtil { private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(bufferAddressField()); + private static final long STRING_VALUE_OFFSET = fieldOffset(stringValueField()); + private UnsafeUtil() {} static boolean hasUnsafeArrayOperations() { @@ -259,6 +260,26 @@ final class UnsafeUtil { return MEMORY_ACCESSOR.getLong(buffer, BUFFER_ADDRESS_OFFSET); } + /** + * Returns a new {@link String} backed by the given {@code chars}. The char array should not + * be mutated any more after calling this function. + */ + static String moveToString(char[] chars) { + if (STRING_VALUE_OFFSET == -1) { + // In the off-chance that this JDK does not implement String as we'd expect, just do a copy. + return new String(chars); + } + final String str; + try { + str = (String) UNSAFE.allocateInstance(String.class); + } catch (InstantiationException e) { + // This should never happen, but return a copy as a fallback just in case. + return new String(chars); + } + putObject(str, STRING_VALUE_OFFSET, chars); + return str; + } + static Object getStaticObject(Field field) { return MEMORY_ACCESSOR.getStaticObject(field); } @@ -366,7 +387,12 @@ final class UnsafeUtil { /** Finds the address field within a direct {@link Buffer}. */ private static Field bufferAddressField() { - return field(Buffer.class, "address"); + return field(Buffer.class, "address", long.class); + } + + /** Finds the value field within a {@link String}. */ + private static Field stringValueField() { + return field(String.class, "value", char[].class); } /** @@ -381,11 +407,14 @@ final class UnsafeUtil { * Gets the field with the given name within the class, or {@code null} if not found. If found, * the field is made accessible. */ - private static Field field(Class<?> clazz, String fieldName) { + private static Field field(Class<?> clazz, String fieldName, Class<?> expectedType) { Field field; try { field = clazz.getDeclaredField(fieldName); field.setAccessible(true); + if (!field.getType().equals(expectedType)) { + return null; + } } catch (Throwable t) { // Failed to access the fields. field = null; |