QPID-8316: [Broker-J] Message validation should not store decoded headers in heap
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
index 7ea7958..3c14ebb 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/FieldTable.java
@@ -109,14 +109,11 @@
         return value;
     }
 
-    private void decode()
+    private Map<String, AMQTypedValue> decode()
     {
+        final Map<String, AMQTypedValue> properties = new HashMap<>();
         if (_encodedSize > 0 && _encodedForm != null)
         {
-            if (!_properties.isEmpty())
-            {
-                _properties.clear();
-            }
             _encodedForm.mark();
             try
             {
@@ -126,7 +123,7 @@
 
                     checkPropertyName(key);
                     AMQTypedValue value = AMQTypedValue.readFromBuffer(_encodedForm);
-                    _properties.put(key, value);
+                    properties.put(key, value);
                 }
                 while (_encodedForm.hasRemaining());
             }
@@ -135,7 +132,7 @@
                 _encodedForm.reset();
             }
 
-            final long recalculateEncodedSize = recalculateEncodedSize();
+            final long recalculateEncodedSize = recalculateEncodedSize(properties);
             if (_encodedSize != recalculateEncodedSize)
             {
                 throw new IllegalStateException(String.format(
@@ -144,6 +141,7 @@
                         recalculateEncodedSize));
             }
         }
+        return properties;
     }
 
     private void decodeIfNecessary()
@@ -152,7 +150,12 @@
         {
             try
             {
-                decode();
+                final Map<String, AMQTypedValue> properties = decode();
+                if (!_properties.isEmpty())
+                {
+                    _properties.clear();
+                }
+                _properties.putAll(properties);
             }
             finally
             {
@@ -344,10 +347,10 @@
         return _encodedSize;
     }
 
-    private synchronized long recalculateEncodedSize()
+    private synchronized long recalculateEncodedSize(final Map<String, AMQTypedValue> properties)
     {
         long size = 0L;
-        for (Map.Entry<String, AMQTypedValue> e : _properties.entrySet())
+        for (Map.Entry<String, AMQTypedValue> e : properties.entrySet())
         {
             String key = e.getKey();
             AMQTypedValue value = e.getValue();
@@ -533,6 +536,9 @@
 
     public synchronized void validate()
     {
-        decodeIfNecessary();
+        if (!_decoded)
+        {
+            decode();
+        }
     }
 }