diff --git a/core/src/main/java/io/grpc/Metadata.java b/core/src/main/java/io/grpc/Metadata.java index 01999e8e84..1b7d7f4246 100644 --- a/core/src/main/java/io/grpc/Metadata.java +++ b/core/src/main/java/io/grpc/Metadata.java @@ -225,7 +225,11 @@ public abstract class Metadata { "Cannot merge non-serializable metadata into serializable metadata without keys"); } } - store.putAll(other.store); + for (MetadataEntry entry : other.store.values()) { + // Must copy the MetadataEntries since they are mutated. If the two Metadata objects are used + // from different threads it would cause thread-safety issues. + store.put(entry.key.name(), new MetadataEntry(entry)); + } } /** @@ -546,6 +550,16 @@ public abstract class Metadata { this.isBinary = isBinary; } + /** + * Copy constructor. + */ + private MetadataEntry(MetadataEntry entry) { + this.parsed = entry.parsed; + this.key = entry.key; + this.isBinary = entry.isBinary; + this.serializedBinary = entry.serializedBinary; + } + @SuppressWarnings("unchecked") public T getParsed(Key key) { T value = (T) parsed;