File protobuf-51026d922970e06475f005b39287963594134b96.patch of Package protobuf.36265
From 51026d922970e06475f005b39287963594134b96 Mon Sep 17 00:00:00 2001
From: Hao Nguyen <haon@google.com>
Date: Wed, 26 Jun 2019 11:01:34 -0700
Subject: [PATCH] Down integrate to GitHub
---
java/core/src/main/java/com/google/protobuf/BooleanArrayList.java | 19
java/core/src/main/java/com/google/protobuf/CodedInputStream.java | 4
java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java | 2
java/core/src/main/java/com/google/protobuf/DoubleArrayList.java | 19
java/core/src/main/java/com/google/protobuf/FloatArrayList.java | 19
java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java | 662 ++++++++--
java/core/src/main/java/com/google/protobuf/IntArrayList.java | 19
java/core/src/main/java/com/google/protobuf/LongArrayList.java | 19
java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java | 104 +
java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java | 37
java/core/src/test/java/com/google/protobuf/TestUtil.java | 2
src/google/protobuf/compiler/java/java_file.cc | 2
12 files changed, 744 insertions(+), 164 deletions(-)
--- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -46,7 +46,6 @@ final class BooleanArrayList extends Abs
implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection {
private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(new boolean[0], 0);
-
static {
EMPTY_LIST.makeImmutable();
}
@@ -161,6 +160,12 @@ final class BooleanArrayList extends Abs
}
@Override
+ public boolean add(Boolean element) {
+ addBoolean(element);
+ return true;
+ }
+
+ @Override
public void add(int index, Boolean element) {
addBoolean(index, element);
}
@@ -168,7 +173,17 @@ final class BooleanArrayList extends Abs
/** Like {@link #add(Boolean)} but more efficient in that it doesn't box the element. */
@Override
public void addBoolean(boolean element) {
- addBoolean(size, element);
+ ensureIsMutable();
+ if (size == array.length) {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ boolean[] newArray = new boolean[length];
+
+ System.arraycopy(array, 0, newArray, 0, size);
+ array = newArray;
+ }
+
+ array[size++] = element;
}
/** Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element. */
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -483,7 +483,9 @@ public abstract class CodedInputStream {
/**
* Returns true if the stream has reached the end of the input. This is the case if either the end
* of the underlying input source has been reached or if the stream has reached a limit created
- * using {@link #pushLimit(int)}.
+ * using {@link #pushLimit(int)}. This function may get blocked when using StreamDecoder as it
+ * invokes {@link #StreamDecoder.tryRefillBuffer(int)} in this function which will try to read
+ * bytes from input.
*/
public abstract boolean isAtEnd() throws IOException;
--- a/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java
+++ b/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java
@@ -34,7 +34,7 @@ package com.google.protobuf;
public final class DiscardUnknownFieldsParser {
/**
- * Warps a given {@link Parser} into a new {@link Parser} that discards unknown fields during
+ * Wraps a given {@link Parser} into a new {@link Parser} that discards unknown fields during
* parsing.
*
* <p>Usage example:
--- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -46,7 +46,6 @@ final class DoubleArrayList extends Abst
implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection {
private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(new double[0], 0);
-
static {
EMPTY_LIST.makeImmutable();
}
@@ -161,6 +160,12 @@ final class DoubleArrayList extends Abst
}
@Override
+ public boolean add(Double element) {
+ addDouble(element);
+ return true;
+ }
+
+ @Override
public void add(int index, Double element) {
addDouble(index, element);
}
@@ -168,7 +173,17 @@ final class DoubleArrayList extends Abst
/** Like {@link #add(Double)} but more efficient in that it doesn't box the element. */
@Override
public void addDouble(double element) {
- addDouble(size, element);
+ ensureIsMutable();
+ if (size == array.length) {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ double[] newArray = new double[length];
+
+ System.arraycopy(array, 0, newArray, 0, size);
+ array = newArray;
+ }
+
+ array[size++] = element;
}
/** Like {@link #add(int, Double)} but more efficient in that it doesn't box the element. */
--- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -46,7 +46,6 @@ final class FloatArrayList extends Abstr
implements FloatList, RandomAccess, PrimitiveNonBoxingCollection {
private static final FloatArrayList EMPTY_LIST = new FloatArrayList(new float[0], 0);
-
static {
EMPTY_LIST.makeImmutable();
}
@@ -160,6 +159,12 @@ final class FloatArrayList extends Abstr
}
@Override
+ public boolean add(Float element) {
+ addFloat(element);
+ return true;
+ }
+
+ @Override
public void add(int index, Float element) {
addFloat(index, element);
}
@@ -167,7 +172,17 @@ final class FloatArrayList extends Abstr
/** Like {@link #add(Float)} but more efficient in that it doesn't box the element. */
@Override
public void addFloat(float element) {
- addFloat(size, element);
+ ensureIsMutable();
+ if (size == array.length) {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ float[] newArray = new float[length];
+
+ System.arraycopy(array, 0, newArray, 0, size);
+ array = newArray;
+ }
+
+ array[size++] = element;
}
/** Like {@link #add(int, Float)} but more efficient in that it doesn't box the element. */
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -58,6 +58,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -79,6 +81,12 @@ import java.util.TreeMap;
public abstract class GeneratedMessageV3 extends AbstractMessage
implements Serializable {
private static final long serialVersionUID = 1L;
+ // Whether to use reflection for FieldAccessor
+ private static boolean forTestUseReflection = false;
+
+ static void setForTestUseReflection(boolean useReflection) {
+ forTestUseReflection = useReflection;
+ }
/**
* For testing. Allows a test to disable the optimization that avoids using
@@ -105,13 +113,20 @@ public abstract class GeneratedMessageV3
}
/**
- * For testing. Allows a test to disable the optimization that avoids using
- * field builders for nested messages until they are requested. By disabling
- * this optimization, existing tests can be reused to test the field builders.
- * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+ * @see #setAlwaysUseFieldBuildersForTesting(boolean)
*/
static void enableAlwaysUseFieldBuildersForTesting() {
- alwaysUseFieldBuilders = true;
+ setAlwaysUseFieldBuildersForTesting(true);
+ }
+
+ /**
+ * For testing. Allows a test to disable/re-enable the optimization that avoids
+ * using field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+ */
+ static void setAlwaysUseFieldBuildersForTesting(boolean useBuilders) {
+ alwaysUseFieldBuilders = useBuilders;
}
/**
@@ -1795,6 +1810,22 @@ public abstract class GeneratedMessageV3
}
}
+ /** Calls invoke and throws a RuntimeException if it fails. */
+ private static RuntimeException handleException(Throwable e) {
+ if (e instanceof ClassCastException) {
+ // Reflection throws a bad param type as an IllegalArgumentException, whereas MethodHandle
+ // throws it as a ClassCastException; convert for backwards compatibility
+ throw new IllegalArgumentException(e);
+ } else if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ } else if (e instanceof Error) {
+ throw (Error) e;
+ } else {
+ throw new RuntimeException(
+ "Unexpected exception thrown by generated accessor method.", e);
+ }
+ }
+
/**
* Gets the map field with the given field number. This method should be
* overridden in the generated message class if the message contains map
@@ -2041,61 +2072,250 @@ public abstract class GeneratedMessageV3
// ---------------------------------------------------------------
private static class SingularFieldAccessor implements FieldAccessor {
+ private interface MethodInvoker {
+ Object get(final GeneratedMessageV3 message);
+
+ Object get(GeneratedMessageV3.Builder<?> builder);
+
+ int getOneofFieldNumber(final GeneratedMessageV3 message);
+
+ int getOneofFieldNumber(final GeneratedMessageV3.Builder<?> builder);
+
+ void set(final GeneratedMessageV3.Builder<?> builder, final Object value);
+
+ boolean has(final GeneratedMessageV3 message);
+
+ boolean has(GeneratedMessageV3.Builder<?> builder);
+
+ void clear(final GeneratedMessageV3.Builder<?> builder);
+ }
+
+ private static final class ReflectionInvoker implements MethodInvoker {
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method setMethod;
+ protected final Method hasMethod;
+ protected final Method hasMethodBuilder;
+ protected final Method clearMethod;
+ protected final Method caseMethod;
+ protected final Method caseMethodBuilder;
+
+ ReflectionInvoker(
+ final FieldDescriptor descriptor,
+ final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName,
+ boolean isOneofField,
+ boolean hasHasMethod) {
+ getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
+ getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
+ Class<?> type = getMethod.getReturnType();
+ setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
+ hasMethod = hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
+ hasMethodBuilder =
+ hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ caseMethod =
+ isOneofField
+ ? getMethodOrDie(messageClass, "get" + containingOneofCamelCaseName + "Case")
+ : null;
+ caseMethodBuilder =
+ isOneofField
+ ? getMethodOrDie(builderClass, "get" + containingOneofCamelCaseName + "Case")
+ : null;
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ return invokeOrDie(getMethod, message);
+ }
+
+ @Override
+ public Object get(GeneratedMessageV3.Builder<?> builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+
+ @Override
+ public int getOneofFieldNumber(final GeneratedMessageV3 message) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ }
+
+ @Override
+ public int getOneofFieldNumber(final GeneratedMessageV3.Builder<?> builder) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ }
+
+ @Override
+ public void set(final GeneratedMessageV3.Builder<?> builder, final Object value) {
+ invokeOrDie(setMethod, builder, value);
+ }
+
+ @Override
+ public boolean has(final GeneratedMessageV3 message) {
+ return (Boolean) invokeOrDie(hasMethod, message);
+ }
+
+ @Override
+ public boolean has(GeneratedMessageV3.Builder<?> builder) {
+ return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+ }
+
+ @Override
+ public void clear(final GeneratedMessageV3.Builder<?> builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ }
+
+ private static final class MethodHandleInvoker implements MethodInvoker {
+ protected final MethodHandle getMethod;
+ protected final MethodHandle getMethodBuilder;
+ protected final MethodHandle setMethod;
+ protected final MethodHandle hasMethod;
+ protected final MethodHandle hasMethodBuilder;
+ protected final MethodHandle clearMethod;
+ protected final MethodHandle caseMethod;
+ protected final MethodHandle caseMethodBuilder;
+
+ MethodHandleInvoker(ReflectionInvoker accessor) throws IllegalAccessException {
+ MethodHandles.Lookup lookup = MethodHandles.publicLookup();
+
+ this.getMethod = lookup.unreflect(accessor.getMethod);
+ this.getMethodBuilder = lookup.unreflect(accessor.getMethodBuilder);
+ this.setMethod = lookup.unreflect(accessor.setMethod);
+ this.hasMethod =
+ (accessor.hasMethod != null) ? lookup.unreflect(accessor.hasMethod) : null;
+ this.hasMethodBuilder = (accessor.hasMethodBuilder != null)
+ ? lookup.unreflect(accessor.hasMethodBuilder) : null;
+ this.clearMethod = lookup.unreflect(accessor.clearMethod);
+ this.caseMethod =
+ (accessor.caseMethod != null) ? lookup.unreflect(accessor.caseMethod) : null;
+ this.caseMethodBuilder = (accessor.caseMethodBuilder != null)
+ ? lookup.unreflect(accessor.caseMethodBuilder) : null;
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ try {
+ return getMethod.invoke(message);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public Object get(GeneratedMessageV3.Builder<?> builder) {
+ try {
+ return getMethodBuilder.invoke(builder);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public int getOneofFieldNumber(final GeneratedMessageV3 message) {
+ try {
+ return ((Internal.EnumLite) caseMethod.invoke(message)).getNumber();
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public int getOneofFieldNumber(final GeneratedMessageV3.Builder<?> builder) {
+ try {
+ return ((Internal.EnumLite) caseMethodBuilder.invoke(builder)).getNumber();
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public void set(final GeneratedMessageV3.Builder<?> builder, final Object value) {
+ try {
+ setMethod.invoke(builder, value);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public boolean has(final GeneratedMessageV3 message) {
+ try {
+ return (Boolean) hasMethod.invoke(message);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public boolean has(GeneratedMessageV3.Builder<?> builder) {
+ try {
+ return (Boolean) hasMethodBuilder.invoke(builder);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public void clear(final GeneratedMessageV3.Builder<?> builder) {
+ try {
+ clearMethod.invoke(builder);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+ }
+
SingularFieldAccessor(
final FieldDescriptor descriptor, final String camelCaseName,
final Class<? extends GeneratedMessageV3> messageClass,
final Class<? extends Builder> builderClass,
final String containingOneofCamelCaseName) {
- field = descriptor;
isOneofField = descriptor.getContainingOneof() != null;
hasHasMethod = supportFieldPresence(descriptor.getFile())
|| (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
- getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
- getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
- type = getMethod.getReturnType();
- setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
- hasMethod =
- hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
- hasMethodBuilder =
- hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
- clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
- caseMethod = isOneofField ? getMethodOrDie(
- messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
- caseMethodBuilder = isOneofField ? getMethodOrDie(
- builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ ReflectionInvoker reflectionInvoker =
+ new ReflectionInvoker(
+ descriptor,
+ camelCaseName,
+ messageClass,
+ builderClass,
+ containingOneofCamelCaseName,
+ isOneofField,
+ hasHasMethod);
+ field = descriptor;
+ type = reflectionInvoker.getMethod.getReturnType();
+ invoker = tryGetMethodHandleInvoke(reflectionInvoker);
+ }
+
+ static MethodInvoker tryGetMethodHandleInvoke(ReflectionInvoker accessor) {
+ if (forTestUseReflection) {
+ return accessor;
+ }
+ try {
+ return new MethodHandleInvoker(accessor);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
}
// Note: We use Java reflection to call public methods rather than
// access private fields directly as this avoids runtime security
// checks.
protected final Class<?> type;
- protected final Method getMethod;
- protected final Method getMethodBuilder;
- protected final Method setMethod;
- protected final Method hasMethod;
- protected final Method hasMethodBuilder;
- protected final Method clearMethod;
- protected final Method caseMethod;
- protected final Method caseMethodBuilder;
protected final FieldDescriptor field;
protected final boolean isOneofField;
protected final boolean hasHasMethod;
-
- private int getOneofFieldNumber(final GeneratedMessageV3 message) {
- return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
- }
-
- private int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) {
- return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
- }
+ protected final MethodInvoker invoker;
@Override
public Object get(final GeneratedMessageV3 message) {
- return invokeOrDie(getMethod, message);
+ return invoker.get(message);
}
@Override
public Object get(GeneratedMessageV3.Builder builder) {
- return invokeOrDie(getMethodBuilder, builder);
+ return invoker.get(builder);
}
@Override
public Object getRaw(final GeneratedMessageV3 message) {
@@ -2107,134 +2327,324 @@ public abstract class GeneratedMessageV3
}
@Override
public void set(final Builder builder, final Object value) {
- invokeOrDie(setMethod, builder, value);
+ invoker.set(builder, value);
}
@Override
public Object getRepeated(final GeneratedMessageV3 message, final int index) {
- throw new UnsupportedOperationException(
- "getRepeatedField() called on a singular field.");
+ throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
}
@Override
public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) {
throw new UnsupportedOperationException(
- "getRepeatedFieldRaw() called on a singular field.");
+ "getRepeatedFieldRaw() called on a singular field.");
}
@Override
public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
- throw new UnsupportedOperationException(
- "getRepeatedField() called on a singular field.");
+ throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
}
@Override
public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
throw new UnsupportedOperationException(
- "getRepeatedFieldRaw() called on a singular field.");
+ "getRepeatedFieldRaw() called on a singular field.");
}
@Override
public void setRepeated(final Builder builder, final int index, final Object value) {
- throw new UnsupportedOperationException(
- "setRepeatedField() called on a singular field.");
+ throw new UnsupportedOperationException("setRepeatedField() called on a singular field.");
}
@Override
public void addRepeated(final Builder builder, final Object value) {
- throw new UnsupportedOperationException(
- "addRepeatedField() called on a singular field.");
+ throw new UnsupportedOperationException("addRepeatedField() called on a singular field.");
}
@Override
public boolean has(final GeneratedMessageV3 message) {
if (!hasHasMethod) {
if (isOneofField) {
- return getOneofFieldNumber(message) == field.getNumber();
+ return invoker.getOneofFieldNumber(message) == field.getNumber();
}
return !get(message).equals(field.getDefaultValue());
}
- return (Boolean) invokeOrDie(hasMethod, message);
+ return invoker.has(message);
}
@Override
public boolean has(GeneratedMessageV3.Builder builder) {
if (!hasHasMethod) {
if (isOneofField) {
- return getOneofFieldNumber(builder) == field.getNumber();
+ return invoker.getOneofFieldNumber(builder) == field.getNumber();
}
return !get(builder).equals(field.getDefaultValue());
}
- return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+ return invoker.has(builder);
}
@Override
public int getRepeatedCount(final GeneratedMessageV3 message) {
throw new UnsupportedOperationException(
- "getRepeatedFieldSize() called on a singular field.");
+ "getRepeatedFieldSize() called on a singular field.");
}
@Override
public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
throw new UnsupportedOperationException(
- "getRepeatedFieldSize() called on a singular field.");
+ "getRepeatedFieldSize() called on a singular field.");
}
@Override
public void clear(final Builder builder) {
- invokeOrDie(clearMethod, builder);
+ invoker.clear(builder);
}
@Override
public Message.Builder newBuilder() {
throw new UnsupportedOperationException(
- "newBuilderForField() called on a non-Message type.");
+ "newBuilderForField() called on a non-Message type.");
}
@Override
public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
- throw new UnsupportedOperationException(
- "getFieldBuilder() called on a non-Message type.");
+ throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
}
@Override
public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
throw new UnsupportedOperationException(
- "getRepeatedFieldBuilder() called on a non-Message type.");
+ "getRepeatedFieldBuilder() called on a non-Message type.");
}
}
private static class RepeatedFieldAccessor implements FieldAccessor {
+ interface MethodInvoker {
+ public Object get(final GeneratedMessageV3 message);
+
+ public Object get(GeneratedMessageV3.Builder<?> builder);
+
+ Object getRepeated(final GeneratedMessageV3 message, final int index);
+
+ Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index);
+
+ void setRepeated(
+ final GeneratedMessageV3.Builder<?> builder, final int index, final Object value);
+
+ void addRepeated(final GeneratedMessageV3.Builder<?> builder, final Object value);
+
+ int getRepeatedCount(final GeneratedMessageV3 message);
+
+ int getRepeatedCount(GeneratedMessageV3.Builder<?> builder);
+
+ void clear(final GeneratedMessageV3.Builder<?> builder);
+ }
+
+ private static final class ReflectionInvoker implements MethodInvoker {
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method getRepeatedMethod;
+ protected final Method getRepeatedMethodBuilder;
+ protected final Method setRepeatedMethod;
+ protected final Method addRepeatedMethod;
+ protected final Method getCountMethod;
+ protected final Method getCountMethodBuilder;
+ protected final Method clearMethod;
+
+ ReflectionInvoker(
+ final FieldDescriptor descriptor,
+ final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List");
+ getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List");
+ getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+ getRepeatedMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
+ Class<?> type = getRepeatedMethod.getReturnType();
+ setRepeatedMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName, Integer.TYPE, type);
+ addRepeatedMethod = getMethodOrDie(builderClass, "add" + camelCaseName, type);
+ getCountMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+ getCountMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ return invokeOrDie(getMethod, message);
+ }
+
+ @Override
+ public Object get(GeneratedMessageV3.Builder<?> builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+
+ @Override
+ public Object getRepeated(
+ final GeneratedMessageV3 message, final int index) {
+ return invokeOrDie(getRepeatedMethod, message, index);
+ }
+
+ @Override
+ public Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index) {
+ return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+ }
+
+ @Override
+ public void setRepeated(
+ final GeneratedMessageV3.Builder<?> builder, final int index, final Object value) {
+ invokeOrDie(setRepeatedMethod, builder, index, value);
+ }
+
+ @Override
+ public void addRepeated(
+ final GeneratedMessageV3.Builder<?> builder, final Object value) {
+ invokeOrDie(addRepeatedMethod, builder, value);
+ }
+
+ @Override
+ public int getRepeatedCount(final GeneratedMessageV3 message) {
+ return (Integer) invokeOrDie(getCountMethod, message);
+ }
+
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3.Builder<?> builder) {
+ return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+ }
+
+ @Override
+ public void clear(final GeneratedMessageV3.Builder<?> builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ }
+
+ private static final class MethodHandleInvoker implements MethodInvoker {
+ protected final MethodHandle getMethod;
+ protected final MethodHandle getMethodBuilder;
+ protected final MethodHandle getRepeatedMethod;
+ protected final MethodHandle getRepeatedMethodBuilder;
+ protected final MethodHandle setRepeatedMethod;
+ protected final MethodHandle addRepeatedMethod;
+ protected final MethodHandle getCountMethod;
+ protected final MethodHandle getCountMethodBuilder;
+ protected final MethodHandle clearMethod;
+
+ MethodHandleInvoker(ReflectionInvoker accessor) throws IllegalAccessException {
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+ this.getMethod = lookup.unreflect(accessor.getMethod);
+ this.getMethodBuilder = lookup.unreflect(accessor.getMethodBuilder);
+ this.getRepeatedMethod = lookup.unreflect(accessor.getRepeatedMethod);
+ this.getRepeatedMethodBuilder = lookup.unreflect(accessor.getRepeatedMethodBuilder);
+ this.setRepeatedMethod = lookup.unreflect(accessor.setRepeatedMethod);
+ this.addRepeatedMethod = lookup.unreflect(accessor.addRepeatedMethod);
+ this.getCountMethod = lookup.unreflect(accessor.getCountMethod);
+ this.getCountMethodBuilder = lookup.unreflect(accessor.getCountMethodBuilder);
+ this.clearMethod = lookup.unreflect(accessor.clearMethod);
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ try {
+ return getMethod.invoke(message);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public Object get(GeneratedMessageV3.Builder<?> builder) {
+ try {
+ return getMethodBuilder.invoke(builder);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message, final int index) {
+ try {
+ return getRepeatedMethod.invoke(message, index);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index) {
+ try {
+ return getRepeatedMethodBuilder.invoke(builder, index);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public void setRepeated(
+ final GeneratedMessageV3.Builder<?> builder, final int index, final Object value) {
+ try {
+ setRepeatedMethod.invoke(builder, index, value);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public void addRepeated(final GeneratedMessageV3.Builder<?> builder, final Object value) {
+ try {
+ addRepeatedMethod.invoke(builder, value);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public int getRepeatedCount(final GeneratedMessageV3 message) {
+ try {
+ return (Integer) getCountMethod.invoke(message);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3.Builder<?> builder) {
+ try {
+ return (Integer) getCountMethodBuilder.invoke(builder);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+
+ @Override
+ public void clear(final GeneratedMessageV3.Builder<?> builder) {
+ try {
+ clearMethod.invoke(builder);
+ } catch (Throwable e) {
+ throw handleException(e);
+ }
+ }
+ }
+
protected final Class type;
- protected final Method getMethod;
- protected final Method getMethodBuilder;
- protected final Method getRepeatedMethod;
- protected final Method getRepeatedMethodBuilder;
- protected final Method setRepeatedMethod;
- protected final Method addRepeatedMethod;
- protected final Method getCountMethod;
- protected final Method getCountMethodBuilder;
- protected final Method clearMethod;
+ protected final MethodInvoker invoker;
RepeatedFieldAccessor(
final FieldDescriptor descriptor, final String camelCaseName,
final Class<? extends GeneratedMessageV3> messageClass,
final Class<? extends Builder> builderClass) {
- getMethod = getMethodOrDie(messageClass,
- "get" + camelCaseName + "List");
- getMethodBuilder = getMethodOrDie(builderClass,
- "get" + camelCaseName + "List");
- getRepeatedMethod =
- getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
- getRepeatedMethodBuilder =
- getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
- type = getRepeatedMethod.getReturnType();
- setRepeatedMethod =
- getMethodOrDie(builderClass, "set" + camelCaseName,
- Integer.TYPE, type);
- addRepeatedMethod =
- getMethodOrDie(builderClass, "add" + camelCaseName, type);
- getCountMethod =
- getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
- getCountMethodBuilder =
- getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+ ReflectionInvoker reflectionInvoker =
+ new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass);
+ type = reflectionInvoker.getRepeatedMethod.getReturnType();
+ invoker = tryGetMethodHandleInvoke(reflectionInvoker);
+ }
- clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ static MethodInvoker tryGetMethodHandleInvoke(ReflectionInvoker accessor) {
+ if (forTestUseReflection) {
+ return accessor;
+ }
+ try {
+ return new MethodHandleInvoker(accessor);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
}
@Override
public Object get(final GeneratedMessageV3 message) {
- return invokeOrDie(getMethod, message);
+ return invoker.get(message);
}
@Override
public Object get(GeneratedMessageV3.Builder builder) {
- return invokeOrDie(getMethodBuilder, builder);
+ return invoker.get(builder);
}
@Override
public Object getRaw(final GeneratedMessageV3 message) {
@@ -2257,11 +2667,11 @@ public abstract class GeneratedMessageV3
}
@Override
public Object getRepeated(final GeneratedMessageV3 message, final int index) {
- return invokeOrDie(getRepeatedMethod, message, index);
+ return invoker.getRepeated(message, index);
}
@Override
public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
- return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+ return invoker.getRepeated(builder, index);
}
@Override
public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
@@ -2273,48 +2683,45 @@ public abstract class GeneratedMessageV3
}
@Override
public void setRepeated(final Builder builder, final int index, final Object value) {
- invokeOrDie(setRepeatedMethod, builder, index, value);
+ invoker.setRepeated(builder, index, value);
}
@Override
public void addRepeated(final Builder builder, final Object value) {
- invokeOrDie(addRepeatedMethod, builder, value);
+ invoker.addRepeated(builder, value);
}
@Override
public boolean has(final GeneratedMessageV3 message) {
- throw new UnsupportedOperationException(
- "hasField() called on a repeated field.");
+ throw new UnsupportedOperationException("hasField() called on a repeated field.");
}
@Override
public boolean has(GeneratedMessageV3.Builder builder) {
- throw new UnsupportedOperationException(
- "hasField() called on a repeated field.");
+ throw new UnsupportedOperationException("hasField() called on a repeated field.");
}
@Override
public int getRepeatedCount(final GeneratedMessageV3 message) {
- return (Integer) invokeOrDie(getCountMethod, message);
+ return invoker.getRepeatedCount(message);
}
@Override
public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
- return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+ return invoker.getRepeatedCount(builder);
}
@Override
public void clear(final Builder builder) {
- invokeOrDie(clearMethod, builder);
+ invoker.clear(builder);
}
@Override
public Message.Builder newBuilder() {
throw new UnsupportedOperationException(
- "newBuilderForField() called on a non-Message type.");
+ "newBuilderForField() called on a non-Message type.");
}
@Override
public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
- throw new UnsupportedOperationException(
- "getFieldBuilder() called on a non-Message type.");
+ throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
}
@Override
public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
throw new UnsupportedOperationException(
- "getRepeatedFieldBuilder() called on a non-Message type.");
+ "getRepeatedFieldBuilder() called on a non-Message type.");
}
}
@@ -2489,10 +2896,8 @@ public abstract class GeneratedMessageV3
enumDescriptor = descriptor.getEnumType();
- valueOfMethod = getMethodOrDie(type, "valueOf",
- EnumValueDescriptor.class);
- getValueDescriptorMethod =
- getMethodOrDie(type, "getValueDescriptor");
+ valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class);
+ getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor");
supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
if (supportUnknownEnumValue) {
@@ -2554,10 +2959,8 @@ public abstract class GeneratedMessageV3
enumDescriptor = descriptor.getEnumType();
- valueOfMethod = getMethodOrDie(type, "valueOf",
- EnumValueDescriptor.class);
- getValueDescriptorMethod =
- getMethodOrDie(type, "getValueDescriptor");
+ valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class);
+ getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor");
supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
if (supportUnknownEnumValue) {
@@ -2605,35 +3008,31 @@ public abstract class GeneratedMessageV3
}
@Override
- public Object getRepeated(final GeneratedMessageV3 message,
- final int index) {
+ public Object getRepeated(final GeneratedMessageV3 message, final int index) {
if (supportUnknownEnumValue) {
int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
}
- return invokeOrDie(getValueDescriptorMethod,
- super.getRepeated(message, index));
+ return invokeOrDie(getValueDescriptorMethod, super.getRepeated(message, index));
}
+
@Override
- public Object getRepeated(final GeneratedMessageV3.Builder builder,
- final int index) {
+ public Object getRepeated(final GeneratedMessageV3.Builder builder, final int index) {
if (supportUnknownEnumValue) {
int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
}
- return invokeOrDie(getValueDescriptorMethod,
- super.getRepeated(builder, index));
+ return invokeOrDie(getValueDescriptorMethod, super.getRepeated(builder, index));
}
+
@Override
- public void setRepeated(final Builder builder,
- final int index, final Object value) {
+ public void setRepeated(final Builder builder, final int index, final Object value) {
if (supportUnknownEnumValue) {
invokeOrDie(setRepeatedValueMethod, builder, index,
((EnumValueDescriptor) value).getNumber());
return;
}
- super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
- value));
+ super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value));
}
@Override
public void addRepeated(final Builder builder, final Object value) {
@@ -2729,7 +3128,8 @@ public abstract class GeneratedMessageV3
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
- .mergeFrom((Message) value).buildPartial();
+ .mergeFrom((Message) value)
+ .buildPartial();
}
}
@@ -2772,13 +3172,13 @@ public abstract class GeneratedMessageV3
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
- .mergeFrom((Message) value).build();
+ .mergeFrom((Message) value)
+ .build();
}
}
@Override
- public void setRepeated(final Builder builder,
- final int index, final Object value) {
+ public void setRepeated(final Builder builder, final int index, final Object value) {
super.setRepeated(builder, index, coerceType(value));
}
@Override
@@ -2809,12 +3209,10 @@ public abstract class GeneratedMessageV3
}
/**
- * Checks that the {@link Extension} is non-Lite and returns it as a
- * {@link GeneratedExtension}.
+ * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}.
*/
private static <MessageType extends ExtendableMessage<MessageType>, T>
- Extension<MessageType, T> checkNotLite(
- ExtensionLite<MessageType, T> extension) {
+ Extension<MessageType, T> checkNotLite(ExtensionLite<MessageType, T> extension) {
if (extension.isLite()) {
throw new IllegalArgumentException("Expected non-lite extension.");
}
--- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -46,7 +46,6 @@ final class IntArrayList extends Abstrac
implements IntList, RandomAccess, PrimitiveNonBoxingCollection {
private static final IntArrayList EMPTY_LIST = new IntArrayList(new int[0], 0);
-
static {
EMPTY_LIST.makeImmutable();
}
@@ -160,6 +159,12 @@ final class IntArrayList extends Abstrac
}
@Override
+ public boolean add(Integer element) {
+ addInt(element);
+ return true;
+ }
+
+ @Override
public void add(int index, Integer element) {
addInt(index, element);
}
@@ -167,7 +172,17 @@ final class IntArrayList extends Abstrac
/** Like {@link #add(Integer)} but more efficient in that it doesn't box the element. */
@Override
public void addInt(int element) {
- addInt(size, element);
+ ensureIsMutable();
+ if (size == array.length) {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ int[] newArray = new int[length];
+
+ System.arraycopy(array, 0, newArray, 0, size);
+ array = newArray;
+ }
+
+ array[size++] = element;
}
/** Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element. */
--- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -46,7 +46,6 @@ final class LongArrayList extends Abstra
implements LongList, RandomAccess, PrimitiveNonBoxingCollection {
private static final LongArrayList EMPTY_LIST = new LongArrayList(new long[0], 0);
-
static {
EMPTY_LIST.makeImmutable();
}
@@ -160,6 +159,12 @@ final class LongArrayList extends Abstra
}
@Override
+ public boolean add(Long element) {
+ addLong(element);
+ return true;
+ }
+
+ @Override
public void add(int index, Long element) {
addLong(index, element);
}
@@ -167,7 +172,17 @@ final class LongArrayList extends Abstra
/** Like {@link #add(Long)} but more efficient in that it doesn't box the element. */
@Override
public void addLong(long element) {
- addLong(size, element);
+ ensureIsMutable();
+ if (size == array.length) {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ long[] newArray = new long[length];
+
+ System.arraycopy(array, 0, newArray, 0, size);
+ array = newArray;
+ }
+
+ array[size++] = element;
}
/** Like {@link #add(int, Long)} but more efficient in that it doesn't box the element. */
--- a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
@@ -31,14 +31,13 @@
package com.google.protobuf;
import com.google.protobuf.Internal.ProtobufList;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
/** Implements {@link ProtobufList} for non-primitive and {@link String} types. */
final class ProtobufArrayList<E> extends AbstractProtobufList<E> {
private static final ProtobufArrayList<Object> EMPTY_LIST =
- new ProtobufArrayList<Object>(new ArrayList<Object>(0));
+ new ProtobufArrayList<Object>(new Object[0], 0);
static {
EMPTY_LIST.makeImmutable();
@@ -49,56 +48,127 @@ final class ProtobufArrayList<E> extends
return (ProtobufArrayList<E>) EMPTY_LIST;
}
- private final List<E> list;
+ private E[] array;
+ private int size;
+ @SuppressWarnings("unchecked")
ProtobufArrayList() {
- this(new ArrayList<E>(DEFAULT_CAPACITY));
+ this((E[]) new Object[DEFAULT_CAPACITY], 0);
}
- private ProtobufArrayList(List<E> list) {
- this.list = list;
+ private ProtobufArrayList(E[] array, int size) {
+ this.array = array;
+ this.size = size;
}
@Override
public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) {
- if (capacity < size()) {
+ if (capacity < size) {
throw new IllegalArgumentException();
}
- List<E> newList = new ArrayList<E>(capacity);
- newList.addAll(list);
- return new ProtobufArrayList<E>(newList);
+
+ E[] newArray = Arrays.copyOf(array, capacity);
+
+ return new ProtobufArrayList<E>(newArray, size);
+ }
+
+ @Override
+ public boolean add(E element) {
+ ensureIsMutable();
+
+ if (size == array.length) {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ E[] newArray = Arrays.copyOf(array, length);
+
+ array = newArray;
+ }
+
+ array[size++] = element;
+ modCount++;
+
+ return true;
}
@Override
public void add(int index, E element) {
ensureIsMutable();
- list.add(index, element);
+
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ E[] newArray = createArray(length);
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
modCount++;
}
@Override
public E get(int index) {
- return list.get(index);
+ ensureIndexInRange(index);
+ return array[index];
}
@Override
public E remove(int index) {
ensureIsMutable();
- E toReturn = list.remove(index);
+ ensureIndexInRange(index);
+
+ E value = array[index];
+ if (index < size - 1) {
+ System.arraycopy(array, index + 1, array, index, size - index - 1);
+ }
+
+ size--;
modCount++;
- return toReturn;
+ return value;
}
@Override
public E set(int index, E element) {
ensureIsMutable();
- E toReturn = list.set(index, element);
+ ensureIndexInRange(index);
+
+ E toReturn = array[index];
+ array[index] = element;
+
modCount++;
return toReturn;
}
@Override
public int size() {
- return list.size();
+ return size;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <E> E[] createArray(int capacity) {
+ return (E[]) new Object[capacity];
+ }
+
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
}
}
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -69,6 +69,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
+import junit.framework.TestSuite;
/**
* Unit test for generated messages and generated code. See also {@link MessageTest}, which tests
@@ -80,6 +81,40 @@ public class GeneratedMessageTest extend
TestUtil.ReflectionTester reflectionTester =
new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTestSuite(ReflectionTest.class);
+ suite.addTestSuite(FastInvokeTest.class);
+ return suite;
+ }
+
+ public static class ReflectionTest extends GeneratedMessageTest {
+ public ReflectionTest() {
+ super(true);
+ }
+ }
+
+ public static class FastInvokeTest extends GeneratedMessageTest {
+ public FastInvokeTest() {
+ super(false);
+ }
+ }
+
+ private final boolean useReflection;
+
+ GeneratedMessageTest(boolean useReflection) {
+ this.useReflection = useReflection;
+ }
+
+ @Override public void setUp() {
+ GeneratedMessageV3.setForTestUseReflection(useReflection);
+ }
+
+ @Override public void tearDown() {
+ GeneratedMessageV3.setForTestUseReflection(false);
+ GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(false);
+ }
+
public void testDefaultInstance() throws Exception {
assertSame(
TestAllTypes.getDefaultInstance(),
@@ -937,7 +972,7 @@ public class GeneratedMessageTest extend
}
public void testInvalidations() throws Exception {
- GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+ GeneratedMessageV3.setAlwaysUseFieldBuildersForTesting(true);
TestAllTypes.NestedMessage nestedMessage1 = TestAllTypes.NestedMessage.newBuilder().build();
TestAllTypes.NestedMessage nestedMessage2 = TestAllTypes.NestedMessage.newBuilder().build();
--- a/java/core/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -2776,7 +2776,7 @@ public final class TestUtil {
}
/** Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. */
- private Descriptors.FieldDescriptor f(String name) {
+ Descriptors.FieldDescriptor f(String name) {
Descriptors.FieldDescriptor result;
if (extensionRegistry == null) {
result = baseDescriptor.findFieldByName(name);
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -521,7 +521,7 @@ void FileGenerator::GenerateDescriptorIn
// we want the mutable code to be independent from the immutable code
// at compile time. It is required to implement dual-compile for
// mutable and immutable API in blaze.
- " java.lang.Class immutableClass = java.lang.Class.forName(\n"
+ " java.lang.Class<?> immutableClass = java.lang.Class.forName(\n"
" \"$immutable_classname$\");\n"
"} catch (java.lang.ClassNotFoundException e) {\n",
"immutable_classname", name_resolver_->GetImmutableClassName(file_));