diff options
author | Ed Merks | 2015-12-09 08:44:22 +0000 |
---|---|---|
committer | Thomas Watson | 2016-02-23 21:55:02 +0000 |
commit | bc100ec508c1afd07a94f16104872c29503446f9 (patch) | |
tree | 71b07204158b18cf456f192c27fb903f9b4f7ab2 | |
parent | da99d5b3806f3d032aa7c99352dc0bd308712e28 (diff) | |
download | rt.equinox.framework-bc100ec508c1afd07a94f16104872c29503446f9.tar.gz rt.equinox.framework-bc100ec508c1afd07a94f16104872c29503446f9.tar.xz rt.equinox.framework-bc100ec508c1afd07a94f16104872c29503446f9.zip |
Bug 483986 Footprint of module representation can be reduced
Change-Id: I4c40ce395e3c2a3a00d79b3b18a03925839466f7
Signed-off-by: Ed Merks <ed.merks@gmail.com>
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
8 files changed, 184 insertions, 85 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java index 63e630486..b9a414e39 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2014 IBM Corporation and others. + * Copyright (c) 2012, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java index aa78ffa7f..2f2cba462 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java @@ -15,7 +15,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.*; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.*; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.eclipse.osgi.container.Module.Settings; @@ -926,7 +926,7 @@ public class ModuleDatabase { } private static class Persistence { - private static final int VERSION = 1; + private static final int VERSION = 2; private static final byte NULL = 0; private static final byte OBJECT = 1; private static final byte LONG_STRING = 3; @@ -965,9 +965,19 @@ public class ModuleDatabase { out.writeInt(moduleDatabase.getInitialModuleStartLevel()); List<Module> modules = moduleDatabase.getModules(); - out.writeInt(modules.size()); - Map<Object, Integer> objectTable = new HashMap<Object, Integer>(); + // prime the object table with all the maps + Set<Map<String, ?>> allMaps = new HashSet<Map<String, ?>>(); + for (Module module : modules) { + getMaps(module, allMaps); + } + out.writeInt(allMaps.size()); + for (Map<String, ?> map : allMaps) { + out.writeInt(addToWriteTable(map, objectTable)); + writeMap(map, out); + } + // prime the object table with all modules + out.writeInt(modules.size()); for (Module module : modules) { writeModule(module, moduleDatabase, out, objectTable); } @@ -999,6 +1009,24 @@ public class ModuleDatabase { out.flush(); } + private static void getMaps(Module module, Set<Map<String, ?>> allMaps) { + ModuleRevision current = module.getCurrentRevision(); + if (current == null) + return; + + List<ModuleCapability> capabilities = current.getModuleCapabilities(null); + for (ModuleCapability capability : capabilities) { + allMaps.add(capability.getPersistentAttributes()); + allMaps.add(capability.getDirectives()); + } + + List<ModuleRequirement> requirements = current.getModuleRequirements(null); + for (ModuleRequirement requirement : requirements) { + allMaps.add(requirement.getAttributes()); + allMaps.add(requirement.getDirectives()); + } + } + public static void load(ModuleDatabase moduleDatabase, DataInputStream in) throws IOException { int version = in.readInt(); if (version > VERSION || VERSION / 1000 != version / 1000) @@ -1008,11 +1036,16 @@ public class ModuleDatabase { moduleDatabase.nextId.set(in.readLong()); moduleDatabase.setInitialModuleStartLevel(in.readInt()); - int numModules = in.readInt(); - Map<Integer, Object> objectTable = new HashMap<Integer, Object>(); + if (version >= 2) { + int numMaps = in.readInt(); + for (int i = 0; i < numMaps; i++) { + readMap(in, objectTable); + } + } + int numModules = in.readInt(); for (int i = 0; i < numModules; i++) { - readModule(moduleDatabase, in, objectTable); + readModule(moduleDatabase, in, objectTable, version); } moduleDatabase.revisionsTimeStamp.set(revisionsTimeStamp); @@ -1065,14 +1098,14 @@ public class ModuleDatabase { out.writeInt(capabilities.size()); for (ModuleCapability capability : capabilities) { out.writeInt(addToWriteTable(capability, objectTable)); - writeGenericInfo(capability.getNamespace(), capability.getPersistentAttributes(), capability.getDirectives(), out); + writeGenericInfo(capability.getNamespace(), capability.getPersistentAttributes(), capability.getDirectives(), out, objectTable); } List<Requirement> requirements = current.getRequirements(null); out.writeInt(requirements.size()); for (Requirement requirement : requirements) { out.writeInt(addToWriteTable(requirement, objectTable)); - writeGenericInfo(requirement.getNamespace(), requirement.getAttributes(), requirement.getDirectives(), out); + writeGenericInfo(requirement.getNamespace(), requirement.getAttributes(), requirement.getDirectives(), out, objectTable); } // settings @@ -1091,7 +1124,7 @@ public class ModuleDatabase { out.writeLong(module.getLastModified()); } - private static void readModule(ModuleDatabase moduleDatabase, DataInputStream in, Map<Integer, Object> objectTable) throws IOException { + private static void readModule(ModuleDatabase moduleDatabase, DataInputStream in, Map<Integer, Object> objectTable, int version) throws IOException { ModuleRevisionBuilder builder = new ModuleRevisionBuilder(); int moduleIndex = in.readInt(); String location = readString(in); @@ -1104,14 +1137,14 @@ public class ModuleDatabase { int[] capabilityIndexes = new int[numCapabilities]; for (int i = 0; i < numCapabilities; i++) { capabilityIndexes[i] = in.readInt(); - readGenericInfo(true, in, builder); + readGenericInfo(true, in, builder, objectTable, version); } int numRequirements = in.readInt(); int[] requirementIndexes = new int[numRequirements]; for (int i = 0; i < numRequirements; i++) { requirementIndexes[i] = in.readInt(); - readGenericInfo(false, in, builder); + readGenericInfo(false, in, builder, objectTable, version); } // settings @@ -1267,17 +1300,24 @@ public class ModuleDatabase { return new ModuleWiring(revision, capabilities, requirements, providedWires, requiredWires, substituted); } - private static void writeGenericInfo(String namespace, Map<String, ?> attributes, Map<String, String> directives, DataOutputStream out) throws IOException { + private static void writeGenericInfo(String namespace, Map<String, ?> attributes, Map<String, String> directives, DataOutputStream out, Map<Object, Integer> objectTable) throws IOException { writeString(namespace, out); - writeMap(attributes, out); - writeMap(directives, out); + + Integer attributesIndex = objectTable.get(attributes); + Integer directivesIndex = objectTable.get(directives); + if (attributesIndex == null || directivesIndex == null) + throw new NullPointerException("Could not find the expected indexes"); //$NON-NLS-1$ + out.writeInt(attributesIndex); + out.writeInt(directivesIndex); } @SuppressWarnings("unchecked") - private static void readGenericInfo(boolean isCapability, DataInputStream in, ModuleRevisionBuilder builder) throws IOException { + private static void readGenericInfo(boolean isCapability, DataInputStream in, ModuleRevisionBuilder builder, Map<Integer, Object> objectTable, int version) throws IOException { String namespace = readString(in); - Map<String, Object> attributes = readMap(in); - Map<String, ?> directives = readMap(in); + Map<String, Object> attributes = version >= 2 ? (Map<String, Object>) objectTable.get(in.readInt()) : readMap(in); + Map<String, ?> directives = version >= 2 ? (Map<String, ?>) objectTable.get(in.readInt()) : readMap(in); + if (attributes == null || directives == null) + throw new NullPointerException("Could not find the expected indexes"); //$NON-NLS-1$ if (isCapability) { builder.basicAddCapability(namespace, (Map<String, String>) directives, attributes); } else { @@ -1328,39 +1368,62 @@ public class ModuleDatabase { } } + private static void readMap(DataInputStream in, Map<Integer, Object> objectTable) throws IOException { + int mapIndex = in.readInt(); + Map<String, Object> result = readMap(in); + addToReadTable(result, mapIndex, objectTable); + } + private static Map<String, Object> readMap(DataInputStream in) throws IOException { int count = in.readInt(); - HashMap<String, Object> result = new HashMap<String, Object>(count); - for (int i = 0; i < count; i++) { + Map<String, Object> result; + if (count == 0) { + result = Collections.emptyMap(); + } else if (count == 1) { String key = readString(in); - Object value = null; byte type = in.readByte(); - if (type == VALUE_STRING) - value = readString(in); - else if (type == VALUE_STRING_ARRAY) - value = readStringArray(in); - else if (type == VAlUE_BOOLEAN) - value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE; - else if (type == VALUE_INTEGER) - value = new Integer(in.readInt()); - else if (type == VALUE_LONG) - value = new Long(in.readLong()); - else if (type == VALUE_DOUBLE) - value = new Double(in.readDouble()); - else if (type == VALUE_VERSION) - value = readVersion(in); - else if (type == VALUE_URI) + Object value = readMapValue(in, type); + result = Collections.singletonMap(key, value); + } else { + result = new HashMap<String, Object>(count); + for (int i = 0; i < count; i++) { + String key = readString(in); + byte type = in.readByte(); + Object value = readMapValue(in, type); + result.put(key, value); + } + result = Collections.unmodifiableMap(result); + } + return result; + } + + private static Object readMapValue(DataInputStream in, int type) throws IOException { + switch (type) { + case VALUE_STRING : + return readString(in); + case VALUE_STRING_ARRAY : + return readStringArray(in); + case VAlUE_BOOLEAN : + return in.readBoolean() ? Boolean.TRUE : Boolean.FALSE; + case VALUE_INTEGER : + return new Integer(in.readInt()); + case VALUE_LONG : + return new Long(in.readLong()); + case VALUE_DOUBLE : + return new Double(in.readDouble()); + case VALUE_VERSION : + return readVersion(in); + case VALUE_URI : try { - value = new URI(readString(in)); + return new URI(readString(in)); } catch (URISyntaxException e) { - value = null; + return null; } - else if (type == VALUE_LIST) - value = readList(in); - - result.put(key, value); + case VALUE_LIST : + return readList(in); + default : + throw new IOException("Invalid type: " + type); //$NON-NLS-1$ } - return result; } private static void writeStringArray(DataOutputStream out, String[] value) throws IOException { @@ -1437,34 +1500,35 @@ public class ModuleDatabase { } private static List<?> readList(DataInputStream in) throws IOException { - int size = in.readInt(); if (size == 0) - return new ArrayList<Object>(0); + return Collections.emptyList(); byte listType = in.readByte(); + if (size == 1) { + return Collections.singletonList(readListValue(listType, in)); + } List<Object> list = new ArrayList<Object>(size); for (int i = 0; i < size; i++) { - switch (listType) { - case VALUE_STRING : - list.add(readString(in)); - break; - case VALUE_INTEGER : - list.add(new Integer(in.readInt())); - break; - case VALUE_LONG : - list.add(new Long(in.readLong())); - break; - case VALUE_DOUBLE : - list.add(new Double(in.readDouble())); - break; - case VALUE_VERSION : - list.add(readVersion(in)); - break; - default : - throw new IOException("Invalid type: " + listType); //$NON-NLS-1$ - } + list.add(readListValue(listType, in)); + } + return Collections.unmodifiableList(list); + } + + private static Object readListValue(byte listType, DataInputStream in) throws IOException { + switch (listType) { + case VALUE_STRING : + return readString(in); + case VALUE_INTEGER : + return new Integer(in.readInt()); + case VALUE_LONG : + return new Long(in.readLong()); + case VALUE_DOUBLE : + return new Double(in.readDouble()); + case VALUE_VERSION : + return readVersion(in); + default : + throw new IOException("Invalid type: " + listType); //$NON-NLS-1$ } - return list; } private static void writeVersion(Version version, DataOutputStream out) throws IOException { @@ -1493,7 +1557,7 @@ public class ModuleDatabase { int minorComponent = in.readInt(); int serviceComponent = in.readInt(); String qualifierComponent = readString(in); - return (Version) ObjectPool.intern(new Version(majorComponent, minorComponent, serviceComponent, qualifierComponent)); + return ObjectPool.intern(new Version(majorComponent, minorComponent, serviceComponent, qualifierComponent)); } private static void writeString(String string, DataOutputStream out) throws IOException { @@ -1524,10 +1588,10 @@ public class ModuleDatabase { in.readFully(data); String string = new String(data, UTF_8); - return (String) ObjectPool.intern(string); + return ObjectPool.intern(string); } - return (String) ObjectPool.intern(in.readUTF()); + return ObjectPool.intern(in.readUTF()); } } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java index c46e5ba66..9bcc3d0bc 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRequirement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2013 IBM Corporation and others. + * Copyright (c) 2012, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,7 +10,8 @@ *******************************************************************************/ package org.eclipse.osgi.container; -import java.util.*; +import java.util.HashMap; +import java.util.Map; import org.eclipse.osgi.internal.container.Capabilities; import org.eclipse.osgi.internal.framework.FilterImpl; import org.osgi.framework.InvalidSyntaxException; @@ -34,8 +35,8 @@ public class ModuleRequirement implements BundleRequirement { ModuleRequirement(String namespace, Map<String, String> directives, Map<String, ?> attributes, ModuleRevision revision) { this.namespace = namespace; - this.directives = Collections.unmodifiableMap(directives); - this.attributes = Collections.unmodifiableMap(attributes); + this.directives = ModuleRevisionBuilder.unmodifiableMap(directives); + this.attributes = ModuleRevisionBuilder.unmodifiableMap(attributes); this.revision = revision; } @@ -139,4 +140,5 @@ public class ModuleRequirement implements BundleRequirement { return ModuleRequirement.this; } } + } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java index e990c7e23..c3cd310ba 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleRevisionBuilder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2014 IBM Corporation and others. + * Copyright (c) 2012, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -28,6 +28,9 @@ import org.osgi.resource.Namespace; * @since 3.10 */ public final class ModuleRevisionBuilder { + private final static Class<?> SINGLETON_MAP_CLASS = Collections.singletonMap(null, null).getClass(); + private final static Class<?> UNMODIFIABLE_MAP_CLASS = Collections.unmodifiableMap(Collections.emptyMap()).getClass(); + /** * Provides information about a capability or requirement */ @@ -235,6 +238,14 @@ public final class ModuleRevisionBuilder { } private static <K, V> Map<K, V> copyUnmodifiableMap(Map<K, V> map) { + int size = map.size(); + if (size == 0) { + return Collections.emptyMap(); + } + if (size == 1) { + Map.Entry<K, V> entry = map.entrySet().iterator().next(); + return Collections.singletonMap(entry.getKey(), entry.getValue()); + } return Collections.unmodifiableMap(new HashMap<K, V>(map)); } @@ -250,6 +261,25 @@ public final class ModuleRevisionBuilder { if (infos == null) { infos = new ArrayList<GenericInfo>(); } - infos.add(new GenericInfo(namespace, Collections.unmodifiableMap(directives), Collections.unmodifiableMap(attributes))); + infos.add(new GenericInfo(namespace, unmodifiableMap(directives), unmodifiableMap(attributes))); + } + + @SuppressWarnings("unchecked") + static <K, V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> map) { + int size = map.size(); + if (size == 0) { + return Collections.emptyMap(); + } + if (size == 1) { + if (map.getClass() != SINGLETON_MAP_CLASS) { + Map.Entry<? extends K, ? extends V> entry = map.entrySet().iterator().next(); + map = Collections.<K, V> singletonMap(entry.getKey(), entry.getValue()); + } + } else { + if (map.getClass() != UNMODIFIABLE_MAP_CLASS) { + map = Collections.unmodifiableMap(map); + } + } + return (Map<K, V>) map; } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java index b881b462d..8a26639be 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleWiring.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2014 IBM Corporation and others. + * Copyright (c) 2012, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -59,7 +59,7 @@ public final class ModuleWiring implements BundleWiring { this.requirements = requirements; this.providedWires = providedWires; this.requiredWires = requiredWires; - this.substitutedPkgNames = substitutedPkgNames; + this.substitutedPkgNames = substitutedPkgNames.isEmpty() ? Collections.<String> emptyList() : substitutedPkgNames; } @Override diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java index 54646a90e..fe047036e 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2014 IBM Corporation and others. + * Copyright (c) 2012, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -128,6 +128,7 @@ public final class OSGiManifestBuilderFactory { } } + @SuppressWarnings("deprecation") private static void checkImportExportSyntax(String headerKey, ManifestElement[] elements, boolean export, boolean dynamic) throws BundleException { if (elements == null) return; @@ -543,6 +544,7 @@ public final class OSGiManifestBuilderFactory { builder.addRequirement(EclipsePlatformNamespace.ECLIPSE_PLATFORM_NAMESPACE, directives, Collections.<String, Object> emptyMap()); } + @SuppressWarnings("deprecation") private static void getEquinoxDataCapability(ModuleRevisionBuilder builder, Map<String, String> manifest) throws BundleException { Map<String, Object> attributes = new HashMap<String, Object>(); @@ -703,7 +705,7 @@ public final class OSGiManifestBuilderFactory { for (String component : tokens) { components.add(convertValue(componentType, component)); } - return components; + return Collections.unmodifiableList(components); } private static void convertBREEs(ModuleRevisionBuilder builder, Map<String, String> manifest) throws BundleException { diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java index ab85ce4c5..548ba1615 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/ObjectPool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corporation and others. + * Copyright (c) 2009, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,13 +23,14 @@ public class ObjectPool { private static final boolean DEBUG_OBJECTPOOL_DUPS = false; private static Map<Object, WeakReference<Object>> objectCache = new WeakHashMap<Object, WeakReference<Object>>(); - public static Object intern(Object obj) { + @SuppressWarnings("unchecked") + public static <T> T intern(T obj) { synchronized (objectCache) { WeakReference<Object> ref = objectCache.get(obj); if (ref != null) { Object refValue = ref.get(); if (refValue != null) { - obj = refValue; + obj = (T) refValue; if (DEBUG_OBJECTPOOL_DUPS) Debug.println("[ObjectPool] Found duplicate object: " + getObjectString(obj)); //$NON-NLS-1$ } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java index a2d68b337..0c460b1b6 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java @@ -1179,7 +1179,7 @@ public class Storage { int numCachedHeaders = in.readInt(); List<String> storedCachedHeaderKeys = new ArrayList<String>(numCachedHeaders); for (int i = 0; i < numCachedHeaders; i++) { - storedCachedHeaderKeys.add((String) ObjectPool.intern(in.readUTF())); + storedCachedHeaderKeys.add(ObjectPool.intern(in.readUTF())); } int numInfos = in.readInt(); @@ -1187,7 +1187,7 @@ public class Storage { List<Generation> generations = new ArrayList<BundleInfo.Generation>(numInfos); for (int i = 0; i < numInfos; i++) { long infoId = in.readLong(); - String infoLocation = (String) ObjectPool.intern(in.readUTF()); + String infoLocation = ObjectPool.intern(in.readUTF()); long nextGenId = in.readLong(); long generationId = in.readLong(); boolean isDirectory = in.readBoolean(); @@ -1202,7 +1202,7 @@ public class Storage { if (NUL.equals(value)) { value = null; } else { - value = (String) ObjectPool.intern(value); + value = ObjectPool.intern(value); } cachedHeaders.put(headerKey, value); } |