From 8897ebc84c1490ad6a83275d39d27b0ed2e6e1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Kubitz?= Date: Wed, 21 Feb 2024 13:11:12 +0100 Subject: [PATCH] [memory] Deduplicate new Strings #2054 Reduces memory used by type hierarchy / call hierarchy. Stored for example in ResolvedBinaryType.uniqueKey https://github.com/eclipse-jdt/eclipse.jdt.core/issues/2054 --- .../compiler/classfmt/AnnotationInfo.java | 3 +- .../compiler/classfmt/ClassFileReader.java | 100 ++++++++++-------- .../internal/compiler/classfmt/FieldInfo.java | 7 +- .../compiler/classfmt/InnerClassInfo.java | 7 +- .../compiler/classfmt/MethodInfo.java | 23 ++-- .../classfmt/RecordComponentInfo.java | 7 +- .../compiler/util/CharDeduplication.java | 4 + .../CompletionUnitStructureRequestor.java | 8 +- .../InternalExtendedCompletionContext.java | 3 +- .../jdt/internal/core/AbstractModule.java | 8 +- .../jdt/internal/core/BinaryMethod.java | 13 ++- .../jdt/internal/core/BinaryModule.java | 3 +- .../eclipse/jdt/internal/core/BinaryType.java | 5 +- .../eclipse/jdt/internal/core/ClassFile.java | 14 +-- .../jdt/internal/core/ClassFileInfo.java | 16 ++- .../internal/core/ClasspathAccessRule.java | 3 +- .../jdt/internal/core/ClasspathEntry.java | 10 +- .../jdt/internal/core/CompilationUnit.java | 3 +- .../CompilationUnitStructureRequestor.java | 40 ++++--- .../jdt/internal/core/JarPackageFragment.java | 3 +- .../internal/core/JarPackageFragmentRoot.java | 4 +- .../jdt/internal/core/JavaElement.java | 2 +- .../jdt/internal/core/JavaModelManager.java | 12 +-- .../jdt/internal/core/LambdaExpression.java | 8 +- .../jdt/internal/core/LambdaFactory.java | 25 +++-- .../jdt/internal/core/LambdaMethod.java | 4 +- .../eclipse/jdt/internal/core/NameLookup.java | 9 +- .../jdt/internal/core/PackageFragment.java | 5 +- .../internal/core/PackageFragmentRoot.java | 4 +- .../internal/core/SearchableEnvironment.java | 7 +- .../jdt/internal/core/SelectionRequestor.java | 3 +- .../jdt/internal/core/SourceMapper.java | 42 ++++---- .../eclipse/jdt/internal/core/SourceType.java | 4 +- .../jdt/internal/core/builder/State.java | 3 +- .../core/hierarchy/HierarchyBuilder.java | 4 +- .../core/hierarchy/HierarchyResolver.java | 5 +- .../internal/core/util/DeduplicationUtil.java | 23 ++++ .../jdt/internal/core/util/HandleFactory.java | 12 +-- .../matching/ClassFileMatchLocator.java | 6 +- .../core/search/matching/MatchLocator.java | 15 +-- .../core/search/matching/PossibleMatch.java | 3 +- 41 files changed, 268 insertions(+), 212 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java index cad63a5b49f..88b9bb436e8 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java @@ -22,6 +22,7 @@ import org.eclipse.jdt.internal.compiler.env.*; import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.lookup.TagBits; +import org.eclipse.jdt.internal.compiler.util.CharDeduplication; import org.eclipse.jdt.internal.compiler.util.Util; public class AnnotationInfo extends ClassFileStruct implements IBinaryAnnotation { @@ -57,7 +58,7 @@ public class AnnotationInfo extends ClassFileStruct implements IBinaryAnnotation private void decodeAnnotation() { this.readOffset = 0; int utf8Offset = this.constantPoolOffsets[u2At(0)] - this.structOffset; - this.typename = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.typename = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); int numberOfPairs = u2At(2); // u2 type_index + u2 num_member_value_pair this.readOffset += 4; diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java index 40561cea8f7..1d82a807f33 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java @@ -48,49 +48,47 @@ import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import org.eclipse.jdt.internal.compiler.util.CharDeduplication; import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.Util; public class ClassFileReader extends ClassFileStruct implements IBinaryType { - private int accessFlags; + private final int accessFlags; private final char[] classFileName; - private char[] className; - private int classNameIndex; - private int constantPoolCount; + private final char[] className; + private final int classNameIndex; + private final int constantPoolCount; private AnnotationInfo[] annotations; private TypeAnnotationInfo[] typeAnnotations; private FieldInfo[] fields; private ModuleInfo moduleDeclaration; public char[] moduleName; - private int fieldsCount; + private final int fieldsCount; // initialized in case the .class file is a nested type private InnerClassInfo innerInfo; private InnerClassInfo[] innerInfos; - private char[][] interfaceNames; - private int interfacesCount; - private char[][] permittedSubtypesNames; + private final char[][] interfaceNames; + private final int interfacesCount; + private final char[][] permittedSubtypesNames; private int permittedSubtypesCount; private MethodInfo[] methods; - private int methodsCount; - private char[] signature; + private final int methodsCount; + private final char[] signature; private char[] sourceName; - private char[] sourceFileName; - private char[] superclassName; + private final char[] sourceFileName; + private final char[] superclassName; private long tagBits; - private long version; - private char[] enclosingTypeName; + private final long version; + private final char[] enclosingTypeName; private char[][][] missingTypeNames; private int enclosingNameAndTypeIndex; private char[] enclosingMethod; - private char[] nestHost; - private int nestMembersCount; - private char[][] nestMembers; private boolean isRecord; private int recordComponentsCount; private RecordComponentInfo[] recordComponents; - URI path; + private URI path; private static String printTypeModifiers(int modifiers) { java.io.StringWriter out = new java.io.StringWriter(); java.io.PrintWriter print = new java.io.PrintWriter(out); @@ -327,14 +325,15 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit } } // Read and validate access flags - this.accessFlags = u2At(readOffset); + int accessFlag = u2At(readOffset); readOffset += 2; // Read the classname, use exception handlers to catch bad format this.classNameIndex = u2At(readOffset); - if (this.classNameIndex != 0) { - this.className = getConstantClassNameAt(this.classNameIndex); + if (this.classNameIndex == 0) { + throw new IllegalArgumentException("No ClassName"); //$NON-NLS-1$ } + this.className = CharDeduplication.intern(getConstantClassNameAt(this.classNameIndex)); readOffset += 2; // Read the superclass name, can be null for java.lang.Object @@ -343,10 +342,12 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit // if superclassNameIndex is equals to 0 there is no need to set a value for the // field this.superclassName. null is fine. if (superclassNameIndex != 0) { - this.superclassName = getConstantClassNameAt(superclassNameIndex); + this.superclassName = CharDeduplication.intern(getConstantClassNameAt(superclassNameIndex)); if (CharOperation.equals(this.superclassName, TypeConstants.CharArray_JAVA_LANG_RECORD_SLASH)) { - this.accessFlags |= ExtraCompilerModifiers.AccRecord; + accessFlag |= ExtraCompilerModifiers.AccRecord; } + } else { + this.superclassName = null; } // Read the interfaces, use exception handlers to catch bad format @@ -355,9 +356,11 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit if (this.interfacesCount != 0) { this.interfaceNames = new char[this.interfacesCount][]; for (int i = 0; i < this.interfacesCount; i++) { - this.interfaceNames[i] = getConstantClassNameAt(u2At(readOffset)); + this.interfaceNames[i] = CharDeduplication.intern(getConstantClassNameAt(u2At(readOffset))); readOffset += 2; } + } else { + this.interfaceNames = null; } // Read the fields, use exception handlers to catch bad format this.fieldsCount = u2At(readOffset); @@ -376,7 +379,7 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit readOffset += 2; if (this.methodsCount != 0) { this.methods = new MethodInfo[this.methodsCount]; - boolean isAnnotationType = (this.accessFlags & ClassFileConstants.AccAnnotation) != 0; + boolean isAnnotationType = (accessFlag & ClassFileConstants.AccAnnotation) != 0; for (int i = 0; i < this.methodsCount; i++) { this.methods[i] = isAnnotationType ? AnnotationMethodInfo.createAnnotationMethod(this.reference, this.constantPoolOffsets, readOffset, this.version) @@ -388,6 +391,10 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit // Read the attributes int attributesCount = u2At(readOffset); readOffset += 2; + char[] enclosingTypeNam = null; + char[] sourceFileNam = null; + char[] signatur = null; + char[][] permittedSubtypesNam = null; for (int i = 0; i < attributesCount; i++) { int utf8Offset = this.constantPoolOffsets[u2At(readOffset)]; @@ -401,13 +408,13 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit if (CharOperation.equals(attributeName, AttributeNamesConstants.EnclosingMethodName)) { utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(readOffset + 6)] + 1)]; - this.enclosingTypeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + enclosingTypeNam = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); this.enclosingNameAndTypeIndex = u2At(readOffset + 8); } break; case 'D' : if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName)) { - this.accessFlags |= ClassFileConstants.AccDeprecated; + accessFlag |= ClassFileConstants.AccDeprecated; } break; case 'I' : @@ -428,7 +435,7 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit if (this.innerInfo != null) { char[] enclosingType = this.innerInfo.getEnclosingTypeName(); if (enclosingType != null) { - this.enclosingTypeName = enclosingType; + enclosingTypeNam = enclosingType; } } } @@ -442,18 +449,18 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit case 'o' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SourceName)) { utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; - this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + sourceFileNam = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } break; case 'y' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) { - this.accessFlags |= ClassFileConstants.AccSynthetic; + accessFlag |= ClassFileConstants.AccSynthetic; } break; case 'i' : if (CharOperation.equals(attributeName, AttributeNamesConstants.SignatureName)) { utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)]; - this.signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + signatur = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } } } @@ -496,17 +503,19 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit if (CharOperation.equals(attributeName, AttributeNamesConstants.NestHost)) { utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(readOffset + 6)] + 1)]; - this.nestHost = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + @SuppressWarnings("unused") + char[] nestHos = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } else if (CharOperation.equals(attributeName, AttributeNamesConstants.NestMembers)) { int offset = readOffset + 6; - this.nestMembersCount = u2At(offset); - if (this.nestMembersCount != 0) { + int nestMembersCount = u2At(offset); + if (nestMembersCount != 0) { offset += 2; - this.nestMembers = new char[this.nestMembersCount][]; - for (int j = 0; j < this.nestMembersCount; j++) { + /** unused */ + char[][] nestMember = new char[nestMembersCount][]; + for (int j = 0; j < nestMembersCount; j++) { utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(offset)] + 1)]; - this.nestMembers[j] = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + nestMember[j] = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); offset += 2; } } @@ -517,13 +526,13 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit int offset = readOffset + 6; this.permittedSubtypesCount = u2At(offset); if (this.permittedSubtypesCount != 0) { - this.accessFlags |= ExtraCompilerModifiers.AccSealed; + accessFlag |= ExtraCompilerModifiers.AccSealed; offset += 2; - this.permittedSubtypesNames = new char[this.permittedSubtypesCount][]; + permittedSubtypesNam = new char[this.permittedSubtypesCount][]; for (int j = 0; j < this.permittedSubtypesCount; j++) { utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(offset)] + 1)]; - this.permittedSubtypesNames[j] = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + permittedSubtypesNam[j] = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); offset += 2; } } @@ -536,6 +545,11 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit this.moduleDeclaration.setAnnotations(this.annotations, this.tagBits, fullyInitialize); this.annotations = null; } + this.accessFlags = accessFlag; + this.enclosingTypeName = enclosingTypeNam; + this.sourceFileName = sourceFileNam; + this.signature = signatur; + this.permittedSubtypesNames= permittedSubtypesNam; if (fullyInitialize) { initialize(); } @@ -566,10 +580,6 @@ private void decodeRecords(int readOffset, char[] attributeName) { } } -public char[] getNestHost() { - return this.nestHost; -} - @Override public ExternalAnnotationStatus getExternalAnnotationStatus() { return ExternalAnnotationStatus.NOT_EEA_CONFIGURED; @@ -708,7 +718,7 @@ public char[] getEnclosingMethod() { utf8Offset = this.constantPoolOffsets[u2At(nameAndTypeOffset + 3)]; buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); - this.enclosingMethod = String.valueOf(buffer).toCharArray(); + this.enclosingMethod = CharDeduplication.intern(buffer.toString().toCharArray()); } return this.enclosingMethod; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java index 6f0d5930589..0929b328116 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java @@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.impl.*; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import org.eclipse.jdt.internal.compiler.util.CharDeduplication; import org.eclipse.jdt.internal.compiler.util.Util; @SuppressWarnings("rawtypes") @@ -191,7 +192,7 @@ public char[] getGenericSignature() { if (this.signatureUtf8Offset != -1) { if (this.signature == null) { // decode the signature - this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1)); + this.signature = CharDeduplication.intern(utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1))); } return this.signature; } @@ -221,7 +222,7 @@ public char[] getName() { if (this.name == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(2)] - this.structOffset; - this.name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.name = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } return this.name; } @@ -245,7 +246,7 @@ public char[] getTypeName() { if (this.descriptor == null) { // read the signature int utf8Offset = this.constantPoolOffsets[u2At(4)] - this.structOffset; - this.descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.descriptor = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } return this.descriptor; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java index 41fcdf3e598..73c9228560f 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java @@ -14,6 +14,7 @@ package org.eclipse.jdt.internal.compiler.classfmt; import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType; +import org.eclipse.jdt.internal.compiler.util.CharDeduplication; /** * Describes one entry in the classes table of the InnerClasses attribute. @@ -48,7 +49,7 @@ public char[] getEnclosingTypeName() { this.constantPoolOffsets[u2At( this.constantPoolOffsets[this.outerClassNameIndex] - this.structOffset + 1)] - this.structOffset; - this.outerClassName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.outerClassName = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } this.readOuterClassName = true; @@ -72,7 +73,7 @@ public char[] getName() { if (this.innerClassNameIndex != 0) { int classOffset = this.constantPoolOffsets[this.innerClassNameIndex] - this.structOffset; int utf8Offset = this.constantPoolOffsets[u2At(classOffset + 1)] - this.structOffset; - this.innerClassName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.innerClassName = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } this.readInnerClassName = true; } @@ -88,7 +89,7 @@ public char[] getSourceName() { if (!this.readInnerName) { if (this.innerNameIndex != 0) { int utf8Offset = this.constantPoolOffsets[this.innerNameIndex] - this.structOffset; - this.innerName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.innerName = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } this.readInnerName = true; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java index 707b9a5507e..e6341e26ac9 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java @@ -24,11 +24,10 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; import org.eclipse.jdt.internal.compiler.lookup.TagBits; +import org.eclipse.jdt.internal.compiler.util.CharDeduplication; @SuppressWarnings("rawtypes") public class MethodInfo extends ClassFileStruct implements IBinaryMethod, Comparable { - static private final char[][] noException = CharOperation.NO_CHAR_CHAR; - static private final char[][] noArgumentNames = CharOperation.NO_CHAR_CHAR; static private final char[] ARG = "arg".toCharArray(); //$NON-NLS-1$ protected int accessFlags; protected int attributeBytes; @@ -281,7 +280,7 @@ public char[] getGenericSignature() { if (this.signatureUtf8Offset != -1) { if (this.signature == null) { // decode the signature - this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1)); + this.signature = CharDeduplication.intern(utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1))); } return this.signature; } @@ -293,7 +292,7 @@ public char[] getMethodDescriptor() { if (this.descriptor == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(4)] - this.structOffset; - this.descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.descriptor = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } return this.descriptor; } @@ -329,7 +328,7 @@ public char[] getSelector() { if (this.name == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(2)] - this.structOffset; - this.name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.name = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } return this.name; } @@ -386,7 +385,7 @@ private synchronized void readExceptionAttributes() { // place the readOffset at the beginning of the exceptions table readOffset += 8; if (entriesNumber == 0) { - names = noException; + names = CharOperation.NO_CHAR_CHAR; } else { names = new char[entriesNumber][]; for (int j = 0; j < entriesNumber; j++) { @@ -403,7 +402,7 @@ private synchronized void readExceptionAttributes() { } } if (names == null) { - this.exceptionNames = noException; + this.exceptionNames = CharOperation.NO_CHAR_CHAR; } else { this.exceptionNames = names; } @@ -470,8 +469,8 @@ private synchronized void readCodeAttribute() { char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (CharOperation.equals(attributeName, AttributeNamesConstants.CodeName)) { decodeCodeAttribute(readOffset); - if (this.argumentNames == null) { - this.argumentNames = noArgumentNames; + if (this.argumentNames == null || this.argumentNames.length == 0) { + this.argumentNames = CharOperation.NO_CHAR_CHAR; } return; } else { @@ -479,7 +478,7 @@ private synchronized void readCodeAttribute() { } } } - this.argumentNames = noArgumentNames; + this.argumentNames = CharOperation.NO_CHAR_CHAR; } private void decodeCodeAttribute(int offset) { int readOffset = offset + 10; @@ -517,7 +516,7 @@ private void decodeLocalVariableAttribute(int offset, int codeLength) { int utf8Offset = this.constantPoolOffsets[nameIndex] - this.structOffset; char[] localVariableName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); if (!CharOperation.equals(localVariableName, ConstantPool.This)) { - names[argumentNamesIndex++] = localVariableName; + names[argumentNamesIndex++] = CharDeduplication.intern(localVariableName); } } else { break; @@ -542,7 +541,7 @@ private void decodeMethodParameters(int offset, MethodInfo methodInfo) { if (nameIndex != 0) { int utf8Offset = this.constantPoolOffsets[nameIndex] - this.structOffset; char[] parameterName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); - names[i] = parameterName; + names[i] = CharDeduplication.intern(parameterName); } else { names[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray()); } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/RecordComponentInfo.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/RecordComponentInfo.java index 7a35dec800d..29e10df5247 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/RecordComponentInfo.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/classfmt/RecordComponentInfo.java @@ -20,6 +20,7 @@ import org.eclipse.jdt.internal.compiler.env.IRecordComponent; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.lookup.TagBits; +import org.eclipse.jdt.internal.compiler.util.CharDeduplication; /* * TODO: Refactor common code from FieldInfo since this mirrors field info mostly except for @@ -175,7 +176,7 @@ public char[] getGenericSignature() { if (this.signatureUtf8Offset != -1) { if (this.signature == null) { // decode the signature - this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1)); + this.signature = CharDeduplication.intern(utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1))); } return this.signature; } @@ -190,7 +191,7 @@ public char[] getName() { if (this.name == null) { // read the name int utf8Offset = this.constantPoolOffsets[u2At(0)] - this.structOffset; - this.name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.name = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } return this.name; } @@ -214,7 +215,7 @@ public char[] getTypeName() { if (this.descriptor == null) { // read the signature int utf8Offset = this.constantPoolOffsets[u2At(2)] - this.structOffset; - this.descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + this.descriptor = CharDeduplication.intern(utf8At(utf8Offset + 3, u2At(utf8Offset + 1))); } return this.descriptor; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/util/CharDeduplication.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/util/CharDeduplication.java index 0b6bf6e6a1c..339d792f7ed 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/util/CharDeduplication.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/util/CharDeduplication.java @@ -64,6 +64,10 @@ public void reset() { Arrays.fill(this.circularBufferPointer, 0); } + public static char[] intern(char[] source) { + return getThreadLocalInstance().sharedCopyOfRange(source, 0, source.length); + } + /** * like Arrays.copyOfRange(source, from, to) but returns a cached instance of the former result if * available diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java index 1bd8465fbf2..4ca8b347072 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionUnitStructureRequestor.java @@ -55,12 +55,12 @@ import org.eclipse.jdt.internal.core.ImportDeclaration; import org.eclipse.jdt.internal.core.Initializer; import org.eclipse.jdt.internal.core.JavaElement; -import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.PackageDeclaration; import org.eclipse.jdt.internal.core.SourceField; import org.eclipse.jdt.internal.core.SourceMethod; import org.eclipse.jdt.internal.core.SourceType; import org.eclipse.jdt.internal.core.TypeParameter; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; public class CompletionUnitStructureRequestor extends CompilationUnitStructureRequestor { private final ASTNode assistNode; @@ -93,7 +93,7 @@ protected Annotation createAnnotation(JavaElement parent, String name) { @Override protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) { - String fieldName = JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name)); + String fieldName = DeduplicationUtil.toString(fieldInfo.name); AssistSourceField field = new AssistSourceField(parent, fieldName, this.bindingCache, this.newElements); FieldDeclaration decl = (FieldDeclaration) (fieldInfo.node); if (decl.binding != null) { @@ -106,7 +106,7 @@ protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) { } @Override protected SourceField createRecordComponent(JavaElement parent, FieldInfo compInfo) { - String compName = JavaModelManager.getJavaModelManager().intern(new String(compInfo.name)); + String compName = DeduplicationUtil.toString(compInfo.name); SourceField comp = new AssistSourceField(parent, compName, this.bindingCache, this.newElements) { @Override public boolean isRecordComponent() throws JavaModelException { @@ -140,7 +140,7 @@ protected Initializer createInitializer(JavaElement parent) { @Override protected SourceMethod createMethodHandle(JavaElement parent, MethodInfo methodInfo) { - String selector = JavaModelManager.getJavaModelManager().intern(new String(methodInfo.name)); + String selector = DeduplicationUtil.toString(methodInfo.name); String[] parameterTypeSigs = convertTypeNamesToSigs(methodInfo.parameterTypes); AssistSourceMethod method = new AssistSourceMethod(parent, selector, parameterTypeSigs, this.bindingCache, this.newElements); if (methodInfo.node.binding != null) { diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java index 7328a89e521..58569714977 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/InternalExtendedCompletionContext.java @@ -69,6 +69,7 @@ import org.eclipse.jdt.internal.core.CompilationUnitElementInfo; import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.LocalVariable; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.Util; public class InternalExtendedCompletionContext { @@ -282,7 +283,7 @@ private JavaElement getJavaElement(LocalVariableBinding binding) { return new LocalVariable( parent, - new String(local.name), + DeduplicationUtil.toString(local.name), local.declarationSourceStart, local.declarationSourceEnd, local.sourceStart, diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java index fb872f76315..79bf793b911 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/AbstractModule.java @@ -96,7 +96,7 @@ default String[] getExportedPackageNames(IModuleDescription targetModule) throws } return result.toArray(new String[result.size()]); } - return new String[0]; + return JavaElement.NO_STRINGS; } @Override default String[] getOpenedPackageNames(IModuleDescription targetModule) throws JavaModelException { @@ -112,7 +112,7 @@ default String[] getOpenedPackageNames(IModuleDescription targetModule) throws J } return result.toArray(new String[result.size()]); } - return new String[0]; + return JavaElement.NO_STRINGS; } default IModuleReference[] getRequiredModules() throws JavaModelException { return getModuleInfo().requires(); @@ -130,7 +130,7 @@ default String[] getProvidedServiceNames() throws JavaModelException { for (IService service : services) { results.add(new String(service.name())); } - return results.toArray(new String[0]); + return results.toArray(String[]::new); } default char[][] getUsedServices() throws JavaModelException { @@ -144,7 +144,7 @@ default String[] getUsedServiceNames() throws JavaModelException { char[] service = services[i]; results.add(new String(service)); } - return results.toArray(new String[0]); + return results.toArray(String[]::new); } default IPackageExport[] getOpenedPackages() throws JavaModelException { return getModuleInfo().opens(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java index 6fbf3eddf38..a6e4973d25f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java @@ -36,6 +36,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.Util; /** @@ -48,7 +49,7 @@ public class BinaryMethod extends BinaryMember implements IMethod { * to perform equality test. CharOperation.NO_STRINGS indicates no * parameters. Note that the parameter type signatures are expected to be dot-based. */ - protected String[] parameterTypes; + protected final String[] parameterTypes; protected String [] erasedParamaterTypes; // lazily initialized via call to getErasedParameterTypes /** @@ -124,7 +125,7 @@ public ILocalVariable[] getParameters() throws JavaModelException { if (i < startIndex) { LocalVariable localVariable = new LocalVariable( this, - new String(argumentNames[i]), + DeduplicationUtil.toString(argumentNames[i]), 0, -1, 0, @@ -531,10 +532,12 @@ public String[] getParameterTypes() { boolean erasureNeeded = false; for (int i = 0; i < paramCount; i++) { String parameterType = this.parameterTypes[i]; - if ((erasedTypes[i] = Signature.getTypeErasure(parameterType)) != parameterType) + if ((erasedTypes[i] = Signature.getTypeErasure(parameterType)) != parameterType) { erasureNeeded = true; + } } - this.erasedParamaterTypes = erasureNeeded ? erasedTypes : this.parameterTypes; + this.erasedParamaterTypes = erasureNeeded ? DeduplicationUtil.intern(erasedTypes) : this.parameterTypes; + } return this.erasedParamaterTypes; } @@ -682,7 +685,7 @@ public String readableName() { } @Override public JavaElement resolved(Binding binding) { - SourceRefElement resolvedHandle = new ResolvedBinaryMethod(this.getParent(), this.name, this.parameterTypes, new String(binding.computeUniqueKey()), this.getOccurrenceCount()); + SourceRefElement resolvedHandle = new ResolvedBinaryMethod(this.getParent(), this.name, this.parameterTypes, DeduplicationUtil.toString(binding.computeUniqueKey()), this.getOccurrenceCount()); return resolvedHandle; }/* * @private Debugging purposes diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java index a95dfaa459e..e22fabc6563 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryModule.java @@ -28,6 +28,7 @@ import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; public class BinaryModule extends BinaryMember implements AbstractModule { @@ -39,7 +40,7 @@ public BinaryModule(JavaElement parent, String name) { } /** For creating a populated handle from a class file. */ public BinaryModule(JavaElement parent, IBinaryModule info) { - super(parent, String.valueOf(info.name())); + super(parent, DeduplicationUtil.toString(info.name())); this.info = info; } @Override diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java index 702e1ab7002..30ab4bd6033 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java @@ -35,6 +35,7 @@ import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -285,7 +286,7 @@ public IType getDeclaringType() { return new BinaryType( (JavaElement)getPackageFragment().getClassFile(enclosingClassFileName), - Util.localTypeName(enclosingName, enclosingName.lastIndexOf('$'), enclosingName.length())); + DeduplicationUtil.intern(Util.localTypeName(enclosingName, enclosingName.lastIndexOf('$'), enclosingName.length()))); } } } @@ -980,7 +981,7 @@ public ITypeHierarchy newTypeHierarchy( } @Override public ResolvedBinaryType resolved(Binding binding) { - return new ResolvedBinaryType(this.getParent(), this.name, new String(binding.computeUniqueKey()), this.getOccurrenceCount()); + return new ResolvedBinaryType(this.getParent(), this.name, DeduplicationUtil.toString(binding.computeUniqueKey()), this.getOccurrenceCount()); } /* * Returns the source file name as defined in the given info. diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java index b8469e1244c..3ff378c9999 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java @@ -58,6 +58,7 @@ import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.nd.java.model.BinaryTypeDescriptor; import org.eclipse.jdt.internal.core.nd.java.model.BinaryTypeFactory; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Util; @@ -70,12 +71,15 @@ public class ClassFile extends AbstractClassFile implements IOrdinaryClassFile { protected BinaryType binaryType = null; private IPath externalAnnotationBase; - + final String typeName; /* * Creates a handle to a class file. */ protected ClassFile(PackageFragment parent, String nameWithoutExtension) { super(parent, nameWithoutExtension); + // Internal class file name doesn't contain ".class" file extension + int lastDollar = this.name.lastIndexOf('$'); + this.typeName = lastDollar > -1 ? DeduplicationUtil.intern(Util.localTypeName(this.name, lastDollar, this.name.length())) : this.name; } /** @@ -386,8 +390,8 @@ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, switch (token.charAt(0)) { case JEM_TYPE: if (!memento.hasMoreTokens()) return this; - String typeName = memento.nextToken(); - JavaElement type = new BinaryType(this, typeName); + String newtypeName = memento.nextToken(); + JavaElement type = new BinaryType(this, DeduplicationUtil.intern(newtypeName)); return type.getHandleFromMemento(memento, owner); } return null; @@ -423,9 +427,7 @@ public IType getType() { return this.binaryType; } public String getTypeName() { - // Internal class file name doesn't contain ".class" file extension - int lastDollar = this.name.lastIndexOf('$'); - return lastDollar > -1 ? Util.localTypeName(this.name, lastDollar, this.name.length()) : this.name; + return this.typeName; } /* * @see IClassFile diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java index 92e1319256c..82c98022535 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; /** * Element info for ClassFile handles. @@ -165,14 +166,13 @@ private void generateFieldInfos(IType type, IBinaryType typeInfo, MapIClasspathContainer. */ - public IPath path; + public final IPath path; /** * Patterns allowing to include/exclude portions of the resource tree denoted by this entry path. @@ -311,17 +312,16 @@ public ClasspathEntry( System.arraycopy(accessRules, 0, rules, 0, length); byte classpathEntryType; String classpathEntryName; - JavaModelManager manager = JavaModelManager.getJavaModelManager(); if (this.entryKind == CPE_PROJECT || this.entryKind == CPE_SOURCE) { // can be remote source entry when reconciling classpathEntryType = AccessRestriction.PROJECT; - classpathEntryName = manager.intern(getPath().segment(0)); + classpathEntryName = DeduplicationUtil.intern(getPath().segment(0)); } else { classpathEntryType = AccessRestriction.LIBRARY; Object target = JavaModel.getWorkspaceTarget(path); if (target == null) { - classpathEntryName = manager.intern(path.toOSString()); + classpathEntryName = DeduplicationUtil.intern(path.toOSString()); } else { - classpathEntryName = manager.intern(path.makeRelative().toString()); + classpathEntryName = DeduplicationUtil.intern(path.makeRelative().toString()); } } this.accessRuleSet = new AccessRuleSet(rules, classpathEntryType, classpathEntryName); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java index 807339434c3..e8e26019bde 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java @@ -33,6 +33,7 @@ import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -587,7 +588,7 @@ public IJavaElement[] findElements(IJavaElement element) { */ @Override public IType findPrimaryType() { - String typeName = Util.getNameWithoutJavaLikeExtension(getElementName()); + String typeName = DeduplicationUtil.intern(Util.getNameWithoutJavaLikeExtension(getElementName())); IType primaryType= getType(typeName); if (primaryType.exists()) { return primaryType; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java index 2e65d707266..8b8ac3ebb8c 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java @@ -51,6 +51,7 @@ import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter; import org.eclipse.jdt.internal.core.util.Util; /** @@ -161,7 +162,7 @@ public void acceptImport(int declarationStart, int declarationEnd, int nameSourc this.newElements.put(this.importContainer, this.importContainerInfo); } - String elementName = JavaModelManager.getJavaModelManager().intern(new String(CharOperation.concatWith(tokens, '.'))); + String elementName = DeduplicationUtil.toString(CharOperation.concatWith(tokens, '.')); ImportDeclaration handle = createImportDeclaration(this.importContainer, elementName, onDemand); resolveDuplicates(handle); @@ -197,7 +198,7 @@ public void acceptPackage(ImportReference importReference) { if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) { char[] name = CharOperation.concatWith(importReference.getImportName(), '.'); - handle = createPackageDeclaration(parentHandle, new String(name)); + handle = createPackageDeclaration(parentHandle, DeduplicationUtil.toString(name)); } else { Assert.isTrue(false); // Should not happen @@ -236,11 +237,11 @@ protected Annotation createAnnotation(JavaElement parent, String name) { return new Annotation(parent, name); } protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) { - String fieldName = JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name)); + String fieldName = DeduplicationUtil.toString(fieldInfo.name); return new SourceField(parent, fieldName); } protected SourceField createRecordComponent(JavaElement parent, FieldInfo compInfo) { - String name = JavaModelManager.getJavaModelManager().intern(new String(compInfo.name)); + String name = DeduplicationUtil.toString(compInfo.name); SourceField field = new SourceField(parent, name) { @Override public boolean isRecordComponent() throws JavaModelException { @@ -259,7 +260,7 @@ protected Initializer createInitializer(JavaElement parent) { return new Initializer(parent, 1); } protected SourceMethod createMethodHandle(JavaElement parent, MethodInfo methodInfo) { - String selector = JavaModelManager.getJavaModelManager().intern(new String(methodInfo.name)); + String selector = DeduplicationUtil.toString(methodInfo.name); String[] parameterTypeSigs = convertTypeNamesToSigs(methodInfo.parameterTypes); return new SourceMethod(parent, selector, parameterTypeSigs); } @@ -267,11 +268,11 @@ protected PackageDeclaration createPackageDeclaration(JavaElement parent, String return new PackageDeclaration((CompilationUnit) parent, name); } protected SourceType createTypeHandle(JavaElement parent, TypeInfo typeInfo) { - String nameString= new String(typeInfo.name); + String nameString= DeduplicationUtil.toString(typeInfo.name); return new SourceType(parent, nameString); } protected SourceModule createModuleHandle(JavaElement parent, ModuleInfo modInfo) { - String nameString= new String(modInfo.moduleName); + String nameString= DeduplicationUtil.toString(modInfo.moduleName); return new org.eclipse.jdt.internal.core.SourceModule(parent, nameString); } protected TypeParameter createTypeParameter(JavaElement parent, String name) { @@ -287,12 +288,11 @@ protected static String[] convertTypeNamesToSigs(char[][] typeNames) { int n = typeNames.length; if (n == 0) return CharOperation.NO_STRINGS; - JavaModelManager manager = JavaModelManager.getJavaModelManager(); String[] typeSigs = new String[n]; for (int i = 0; i < n; ++i) { - typeSigs[i] = manager.intern(Signature.createTypeSignature(typeNames[i], false)); + typeSigs[i] = Signature.createTypeSignature(typeNames[i], false); } - return typeSigs; + return DeduplicationUtil.intern(typeSigs); } protected IAnnotation acceptAnnotation(org.eclipse.jdt.internal.compiler.ast.Annotation annotation, AnnotatableInfo parentInfo, JavaElement parentHandle) { String nameString = new String(CharOperation.concatWith(annotation.type.getTypeName(), '.')); @@ -446,17 +446,16 @@ private SourceMethodElementInfo createMethodInfo(MethodInfo methodInfo, SourceMe info.setNameSourceStart(methodInfo.nameSourceStart); info.setNameSourceEnd(methodInfo.nameSourceEnd); info.setFlags(flags); - JavaModelManager manager = JavaModelManager.getJavaModelManager(); char[][] parameterNames = methodInfo.parameterNames; for (int i = 0, length = parameterNames.length; i < length; i++) - parameterNames[i] = manager.intern(parameterNames[i]); + parameterNames[i] = DeduplicationUtil.intern(parameterNames[i]); info.setArgumentNames(parameterNames); char[] returnType = methodInfo.returnType == null ? new char[]{'v', 'o','i', 'd'} : methodInfo.returnType; - info.setReturnType(manager.intern(returnType)); + info.setReturnType(DeduplicationUtil.intern(returnType)); char[][] exceptionTypes = methodInfo.exceptionTypes; info.setExceptionTypeNames(exceptionTypes); for (int i = 0, length = exceptionTypes.length; i < length; i++) - exceptionTypes[i] = manager.intern(exceptionTypes[i]); + exceptionTypes[i] = DeduplicationUtil.intern(exceptionTypes[i]); this.newElements.put(handle, info); if (methodInfo.typeParameters != null) { @@ -495,10 +494,10 @@ private LocalVariable[] acceptMethodParameters(Argument[] arguments, JavaElement localVarInfo.setNameSourceStart(argument.sourceStart); localVarInfo.setNameSourceEnd(argument.sourceEnd); - String paramTypeSig = JavaModelManager.getJavaModelManager().intern(Signature.createTypeSignature(methodInfo.parameterTypes[i], false)); + String paramTypeSig = DeduplicationUtil.intern(Signature.createTypeSignature(methodInfo.parameterTypes[i], false)); result[i] = new LocalVariable( methodHandle, - new String(argument.name), + DeduplicationUtil.toString(argument.name), argument.declarationSourceStart, argument.declarationSourceEnd, argument.sourceStart, @@ -585,16 +584,15 @@ public boolean isAnonymousMember() { info.setFlags(typeInfo.modifiers); info.setNameSourceStart(typeInfo.nameSourceStart); info.setNameSourceEnd(typeInfo.nameSourceEnd); - JavaModelManager manager = JavaModelManager.getJavaModelManager(); char[] superclass = typeInfo.superclass; - info.setSuperclassName(superclass == null ? null : manager.intern(superclass)); + info.setSuperclassName(superclass == null ? null : DeduplicationUtil.intern(superclass)); char[][] typeNames = typeInfo.superinterfaces; for (int i = 0, length = typeNames == null ? 0 : typeNames.length; i < length; i++) - typeNames[i] = manager.intern(typeNames[i]); + typeNames[i] = DeduplicationUtil.intern(typeNames[i]); info.setSuperInterfaceNames(typeNames); typeNames = typeInfo.permittedSubtypes; for (int i = 0, length = typeNames == null ? 0 : typeNames.length; i < length; i++) - typeNames[i] = manager.intern(typeNames[i]); + typeNames[i] = DeduplicationUtil.intern(typeNames[i]); info.setPermittedSubtypeNames(typeNames); info.addCategories(handle, typeInfo.categories); this.newElements.put(handle, info); @@ -694,7 +692,7 @@ public void exitField(int initializationStart, int declarationEnd, int declarati info.setNameSourceEnd(fieldInfo.nameSourceEnd); info.setSourceRangeStart(fieldInfo.declarationStart); info.setFlags(fieldInfo.modifiers); - char[] typeName = JavaModelManager.getJavaModelManager().intern(fieldInfo.type); + char[] typeName = DeduplicationUtil.intern(fieldInfo.type); info.setTypeName(typeName); info.isRecordComponent = fieldInfo.isRecordComponent; this.newElements.put(handle, info); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java index 77a607f5ac4..ddad310cc1d 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java @@ -29,6 +29,7 @@ import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.Util; /** @@ -79,7 +80,7 @@ private IJavaElement[] computeChildren(ArrayList namesWithoutExtension) { if (TypeConstants.MODULE_INFO_NAME_STRING.equals(nameWithoutExtension)) children[i] = new ModularClassFile(this); else - children[i] = new ClassFile(this, nameWithoutExtension); + children[i] = new ClassFile(this, DeduplicationUtil.intern(nameWithoutExtension)); } return children; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java index f331d97f3d2..55a38f02351 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java @@ -42,6 +42,7 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject; import org.eclipse.jdt.internal.core.util.Util; @@ -366,12 +367,11 @@ protected void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, Strin if (existing != null) break; existingLength--; } - JavaModelManager manager = JavaModelManager.getJavaModelManager(); for (int i = existingLength; i < length; i++) { // sourceLevel must be null because we know nothing about it based on a jar file if (Util.isValidFolderNameForPackage(pkgName[i], null, compliance)) { System.arraycopy(existing, 0, existing = new String[i+1], 0, i); - existing[i] = manager.intern(pkgName[i]); + existing[i] = DeduplicationUtil.intern(pkgName[i]); rawPackageInfo.put(existing, new ArrayList[] { EMPTY_LIST, EMPTY_LIST }); } else { // non-Java resource folder diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java index 03b6848ca47..984ea7030ef 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java @@ -130,7 +130,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement /** cached result */ private int hashCode; - protected static final String[] NO_STRINGS = new String[0]; + public static final String[] NO_STRINGS = new String[0]; protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0]; protected static final Object NO_INFO = new Object(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java index 7a77300b854..840501bd856 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java @@ -3488,14 +3488,6 @@ public void removed(IEclipsePreferences.NodeChangeEvent event) { ((IEclipsePreferences) this.preferencesLookup[PREF_DEFAULT].parent()).addNodeChangeListener(this.defaultNodeListener); } - public char[] intern(char[] array) { - return DeduplicationUtil.intern(array); - } - - public String intern(String s) { - return DeduplicationUtil.intern(s); - } - void touchProjectsAsync(final IProject[] projectsToTouch) throws JavaModelException { for (IProject iProject : projectsToTouch) { this.touchQueue.add(iProject); @@ -5166,10 +5158,10 @@ private static Map> secondaryTypesSearching(IJavaProj IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() { @Override public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) { - String key = packageName==null ? "" : new String(packageName); //$NON-NLS-1$ + String key = packageName==null ? "" : DeduplicationUtil.toString(packageName); //$NON-NLS-1$ Map types = secondaryTypesSearch.get(key); if (types == null) types = new HashMap<>(3); - types.put(new String(simpleTypeName), path); + types.put(DeduplicationUtil.toString(simpleTypeName), path); secondaryTypesSearch.put(key, types); } }; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java index 95050066529..d9d6e100d67 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java @@ -31,6 +31,7 @@ import org.eclipse.jdt.internal.compiler.lookup.Substitution; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Util; @@ -54,7 +55,7 @@ public class LambdaExpression extends SourceType { this.arrowPosition = lambdaExpression.arrowPosition; TypeBinding supertype = findLambdaSuperType(lambdaExpression); - this.interphase = new String(CharOperation.replaceOnCopy(supertype.genericTypeSignature(), '/', '.')); + this.interphase = DeduplicationUtil.toString(CharOperation.replaceOnCopy(supertype.genericTypeSignature(), '/', '.')); this.elementInfo = makeTypeElementInfo(this, this.interphase, this.sourceStart, this.sourceEnd, this.arrowPosition); this.lambdaMethod = LambdaFactory.createLambdaMethod(this, lambdaExpression); this.elementInfo.children = new IJavaElement[] { this.lambdaMethod }; @@ -134,8 +135,7 @@ static private SourceTypeElementInfo makeTypeElementInfo (LambdaExpression handl elementInfo.setSuperclassName(null); elementInfo.addCategories(handle, null); - JavaModelManager manager = JavaModelManager.getJavaModelManager(); - char[][] superinterfaces = new char [][] { manager.intern(Signature.toString(interphase).toCharArray()) }; // drops marker interfaces - to fix. + char[][] superinterfaces = new char [][] { DeduplicationUtil.intern(Signature.toString(interphase).toCharArray()) }; // drops marker interfaces - to fix. elementInfo.setSuperInterfaceNames(superinterfaces); return elementInfo; } @@ -257,7 +257,7 @@ public boolean isLocal() { @Override public ResolvedLambdaExpression resolved(Binding binding) { - return new ResolvedLambdaExpression(this.getParent(), this, new String(binding.computeUniqueKey())); + return new ResolvedLambdaExpression(this.getParent(), this, DeduplicationUtil.toString(binding.computeUniqueKey())); } public IMethod getMethod() { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java index 0447bd6f034..30baee42702 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; public class LambdaFactory { @@ -40,24 +41,23 @@ public static LambdaExpression createLambdaExpression(JavaElement parent, String public static LambdaMethod createLambdaMethod(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) { int length; - JavaModelManager manager = JavaModelManager.getJavaModelManager(); String [] parameterTypes = new String[length = lambdaExpression.descriptor.parameters.length]; for (int i = 0; i < length; i++) - parameterTypes[i] = getTypeSignature(manager, lambdaExpression.descriptor.parameters[i]); + parameterTypes[i] = getTypeSignature(lambdaExpression.descriptor.parameters[i]); String [] parameterNames = new String[length]; for (int i = 0; i < length; i++) - parameterNames[i] = manager.intern(new String(lambdaExpression.arguments[i].name)); - String returnType = getTypeSignature(manager, lambdaExpression.descriptor.returnType); - String selector = manager.intern(new String(lambdaExpression.descriptor.selector)); - String key = new String(lambdaExpression.descriptor.computeUniqueKey()); + parameterNames[i] = DeduplicationUtil.toString(lambdaExpression.arguments[i].name); + String returnType = getTypeSignature(lambdaExpression.descriptor.returnType); + String selector = DeduplicationUtil.toString(lambdaExpression.descriptor.selector); + String key = DeduplicationUtil.toString(lambdaExpression.descriptor.computeUniqueKey()); LambdaMethod lambdaMethod = createLambdaMethod(parent, selector, key, lambdaExpression.sourceStart, lambdaExpression.sourceEnd, lambdaExpression.arrowPosition, parameterTypes, parameterNames, returnType); ILocalVariable [] parameters = new ILocalVariable[length = lambdaExpression.arguments.length]; for (int i = 0; i < length; i++) { Argument argument = lambdaExpression.arguments[i]; - String signature = manager.intern(new String(lambdaExpression.descriptor.parameters[i].signature())); + String signature = DeduplicationUtil.toString(lambdaExpression.descriptor.parameters[i].signature()); parameters[i] = new LocalVariable( lambdaMethod, - new String(argument.name), + DeduplicationUtil.toString(argument.name), argument.declarationSourceStart, argument.declarationSourceEnd, argument.sourceStart, @@ -80,13 +80,12 @@ public static LambdaMethod createLambdaMethod(JavaElement parent, String selecto info.setFlags(0); info.setNameSourceStart(sourceStart); info.setNameSourceEnd(arrowPosition); - JavaModelManager manager = JavaModelManager.getJavaModelManager(); int length; char[][] argumentNames = new char[length = parameterNames.length][]; for (int i = 0; i < length; i++) - argumentNames[i] = manager.intern(parameterNames[i].toCharArray()); + argumentNames[i] = DeduplicationUtil.intern(parameterNames[i].toCharArray()); info.setArgumentNames(argumentNames); - info.setReturnType(manager.intern(Signature.toCharArray(returnType.toCharArray()))); + info.setReturnType(DeduplicationUtil.intern(Signature.toCharArray(returnType.toCharArray()))); info.setExceptionTypeNames(CharOperation.NO_CHAR_CHAR); info.arguments = null; // will be updated shortly, parent has to come into existence first. @@ -94,10 +93,10 @@ public static LambdaMethod createLambdaMethod(JavaElement parent, String selecto new LambdaMethod(parent, selector, key, sourceStart, parameterTypes, parameterNames, returnType, info); } - private static String getTypeSignature(JavaModelManager manager, TypeBinding type) { + private static String getTypeSignature(TypeBinding type) { char[] signature = type.genericTypeSignature(); signature = CharOperation.replaceOnCopy(signature, '/', '.'); - return manager.intern(new String(signature)); + return DeduplicationUtil.toString(signature); } private static boolean isBinaryMember(JavaElement element) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java index c7e8a3027c1..404cbcdb42b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; +import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.core.util.Util; @@ -33,7 +34,8 @@ public class LambdaMethod extends SourceMethod { LambdaMethod(JavaElement parent, String name, String key, int sourceStart, String [] parameterTypes, String [] parameterNames, String returnType, SourceMethodElementInfo elementInfo) { super(parent, name, parameterTypes); this.sourceStart = sourceStart; - this.parameterNameStrings = parameterNames; + this.parameterNameStrings = (parameterNames == null || parameterNames.length == 0) ? CharOperation.NO_STRINGS + : parameterNames; this.returnTypeString = returnType; this.elementInfo = elementInfo; this.key = key; diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java index 2f143d4947d..116bce877c7 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java @@ -48,6 +48,7 @@ import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.AbstractModule.AutoModule; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -1096,7 +1097,7 @@ private IType getMemberType(IType type, String name, int dot) { while (dot != -1) { int start = dot+1; dot = name.indexOf('.', start); - String typeName = name.substring(start, dot == -1 ? name.length() : dot); + String typeName = DeduplicationUtil.intern(name.substring(start, dot == -1 ? name.length() : dot)); type = type.getType(typeName); } return type; @@ -1446,7 +1447,7 @@ public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, i // look in model switch (packageFlavor) { case IPackageFragmentRoot.K_BINARY : - matchName= matchName.replace('.', '$'); + matchName= DeduplicationUtil.intern(matchName.replace('.', '$')); seekTypesInBinaryPackage(matchName, pkg, partialMatch, acceptFlags, requestor); break; case IPackageFragmentRoot.K_SOURCE : @@ -1471,6 +1472,7 @@ public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, i * Performs type search in a binary package. */ protected void seekTypesInBinaryPackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) { + name= DeduplicationUtil.intern(name); long start = -1; if (VERBOSE) start = System.currentTimeMillis(); @@ -1537,7 +1539,8 @@ protected void seekTypesInSourcePackage( String topLevelTypeName, int acceptFlags, IJavaElementRequestor requestor) { - + name= DeduplicationUtil.intern(name); + topLevelTypeName= DeduplicationUtil.intern(topLevelTypeName); long start = -1; if (VERBOSE) start = System.currentTimeMillis(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java index 54eba8e386e..6d3dca161f7 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java @@ -45,6 +45,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -97,7 +98,7 @@ protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, && !Util.isExcluded(child, inclusionPatterns, exclusionPatterns)) { IJavaElement childElement; if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName(), sourceLevel, complianceLevel)) { - childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY); + childElement = new CompilationUnit(this, DeduplicationUtil.intern(child.getName()), DefaultWorkingCopyOwner.PRIMARY); vChildren.add(childElement); } else if (kind == IPackageFragmentRoot.K_BINARY && Util.isValidClassFileName(child.getName(), sourceLevel, complianceLevel)) { childElement = getClassFile(child.getName()); @@ -218,7 +219,7 @@ public IOrdinaryClassFile getOrdinaryClassFile(String classFileName) { int length = classFileName.length() - 6; char[] nameWithoutExtension = new char[length]; classFileName.getChars(0, length, nameWithoutExtension, 0); - return new ClassFile(this, new String(nameWithoutExtension)); + return new ClassFile(this, DeduplicationUtil.toString(nameWithoutExtension)); } /** * @see IPackageFragment#getClassFile(String) diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java index 37a7efa4573..05fb7f1f9ad 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java @@ -26,6 +26,7 @@ import org.eclipse.jdt.internal.compiler.env.AutomaticModuleNaming; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; @@ -251,7 +252,6 @@ protected void computeFolderChildren(IContainer folder, boolean isIncluded, Stri String sourceLevel = otherJavaProject.getOption(JavaCore.COMPILER_SOURCE, true); String complianceLevel = otherJavaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true); JavaProject javaProject = getJavaProject(); - JavaModelManager manager = JavaModelManager.getJavaModelManager(); for (int i = 0; i < length; i++) { IResource member = members[i]; String memberName = member.getName(); @@ -264,7 +264,7 @@ protected void computeFolderChildren(IContainer folder, boolean isIncluded, Stri if (Util.isValidFolderNameForPackage(memberName, sourceLevel, complianceLevel)) { // eliminate binary output only if nested inside direct subfolders if (javaProject.contains(member)) { - String[] newNames = Util.arrayConcat(pkgName, manager.intern(memberName)); + String[] newNames = Util.arrayConcat(pkgName, DeduplicationUtil.intern(memberName)); boolean isMemberIncluded = !Util.isExcluded(member, inclusionPatterns, exclusionPatterns); computeFolderChildren((IFolder) member, isMemberIncluded, newNames, vChildren, inclusionPatterns, exclusionPatterns); } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java index f76a26c8563..1f7d0dc59ae 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java @@ -59,6 +59,7 @@ import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor; import org.eclipse.jdt.internal.core.search.indexing.IndexManager; import org.eclipse.jdt.internal.core.search.processing.IJob; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.Util; /** @@ -526,7 +527,7 @@ public NameEnvironmentAnswer findType(char[][] compoundTypeName, char[] moduleNa System.arraycopy(compoundTypeName, 0, packageName, 0, lengthM1); return find( - new String(compoundTypeName[lengthM1]), + DeduplicationUtil.toString(compoundTypeName[lengthM1]), CharOperation.toString(packageName), moduleLocations); } @@ -541,8 +542,8 @@ public NameEnvironmentAnswer findType(char[] name, char[][] packageName, char[] boolean isNamedStrategy = LookupStrategy.get(moduleName) == LookupStrategy.Named; IPackageFragmentRoot[] moduleLocations = isNamedStrategy ? findModuleContext(moduleName) : null; return find( - new String(name), - packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName), + DeduplicationUtil.toString(name), + packageName == null || packageName.length == 0 ? null : CharOperation.toString(packageName), moduleLocations); } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java index c9e455878f4..1d418054843 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java @@ -53,6 +53,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.core.NameLookup.Answer; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.HandleFactory; import org.eclipse.jdt.internal.core.util.Util; @@ -444,7 +445,7 @@ public void acceptLocalVariable(LocalVariableBinding binding, org.eclipse.jdt.in } localVar = new LocalVariable( (JavaElement)parent, - new String(local.name), + DeduplicationUtil.toString(local.name), local.declarationSourceStart, local.declarationSourceEnd, local.sourceStart, diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java index f2203052b0f..cb5e33037dd 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java @@ -28,6 +28,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -73,6 +74,7 @@ import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.compiler.util.Util; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter; /** @@ -92,10 +94,15 @@ public class SourceMapper implements ISourceElementRequestor, SuffixConstants { public static class LocalVariableElementKey { - String parent; - String name; + private final String parent; + private final String name; public LocalVariableElementKey(IJavaElement method, String name) { + this.parent =DeduplicationUtil.intern(toString(method)); + this.name = name; + } + + private static String toString(IJavaElement method) { StringBuilder buffer = new StringBuilder(); buffer .append(method.getParent().getHandleIdentifier()) @@ -112,8 +119,7 @@ public LocalVariableElementKey(IJavaElement method, String name) { } } buffer.append(')'); - this.parent = String.valueOf(buffer); - this.name = name; + return buffer.toString(); } @Override @@ -134,15 +140,9 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; LocalVariableElementKey other = (LocalVariableElementKey) obj; - if (this.name == null) { - if (other.name != null) - return false; - } else if (!this.name.equals(other.name)) + if (!Objects.equals(this.name, other.name)) return false; - if (this.parent == null) { - if (other.parent != null) - return false; - } else if (!this.parent.equals(other.parent)) + if (!Objects.equals(this.parent, other.parent)) return false; return true; } @@ -828,10 +828,10 @@ public void enterType(TypeInfo typeInfo) { if (this.anonymousCounter == this.anonymousClassName) { this.types[this.typeDepth] = getType(this.binaryTypeOrModule.getElementName()); } else { - this.types[this.typeDepth] = getType(new String(typeInfo.name)); + this.types[this.typeDepth] = getType(DeduplicationUtil.toString(typeInfo.name)); } } else { - this.types[this.typeDepth] = getType(new String(typeInfo.name)); + this.types[this.typeDepth] = getType(DeduplicationUtil.toString(typeInfo.name)); } this.typeNameRanges[this.typeDepth] = new SourceRange(typeInfo.nameSourceStart, typeInfo.nameSourceEnd - typeInfo.nameSourceStart + 1); @@ -913,7 +913,7 @@ public void enterField(FieldInfo fieldInfo) { this.memberDeclarationStart[this.typeDepth] = fieldInfo.declarationStart; this.memberNameRange[this.typeDepth] = new SourceRange(fieldInfo.nameSourceStart, fieldInfo.nameSourceEnd - fieldInfo.nameSourceStart + 1); - String fieldName = new String(fieldInfo.name); + String fieldName = DeduplicationUtil.toString(fieldInfo.name); this.memberName[this.typeDepth] = fieldName; // categories @@ -942,7 +942,7 @@ public void enterMethod(MethodInfo methodInfo) { } private void enterAbstractMethod(MethodInfo methodInfo) { if (this.typeDepth >= 0) { - this.memberName[this.typeDepth] = new String(methodInfo.name); + this.memberName[this.typeDepth] = DeduplicationUtil.toString(methodInfo.name); this.memberNameRange[this.typeDepth] = new SourceRange(methodInfo.nameSourceStart, methodInfo.nameSourceEnd - methodInfo.nameSourceStart + 1); this.memberDeclarationStart[this.typeDepth] = methodInfo.declarationStart; @@ -979,7 +979,7 @@ private void enterAbstractMethod(MethodInfo methodInfo) { IMethod method = currentType.getMethod( this.memberName[this.typeDepth], - convertTypeNamesToSigs(this.methodParameterTypes[this.typeDepth])); + DeduplicationUtil.intern(convertTypeNamesToSigs(this.methodParameterTypes[this.typeDepth]))); // type parameters if (methodInfo.typeParameters != null) { @@ -1000,7 +1000,7 @@ private void enterAbstractMethod(MethodInfo methodInfo) { if (methodInfo.parameterInfos != null) { for (int i = 0, length = methodInfo.parameterInfos.length; i < length; i++) { ParameterInfo parameterInfo = methodInfo.parameterInfos[i]; - LocalVariableElementKey key = new LocalVariableElementKey(method, new String(parameterInfo.name)); + LocalVariableElementKey key = new LocalVariableElementKey(method, DeduplicationUtil.toString(parameterInfo.name)); SourceRange[] allRanges = new SourceRange[] { new SourceRange( parameterInfo.declarationStart, @@ -1099,7 +1099,7 @@ private void exitAbstractMethod(int declarationEnd) { declarationEnd - this.memberDeclarationStart[this.typeDepth] + 1); IMethod method = currentType.getMethod( this.memberName[this.typeDepth], - convertTypeNamesToSigs(this.methodParameterTypes[this.typeDepth])); + DeduplicationUtil.intern(convertTypeNamesToSigs(this.methodParameterTypes[this.typeDepth]))); setSourceRange( method, sourceRange, @@ -1409,7 +1409,7 @@ protected IType getType(String typeName) { newClassFileName.append(classFileName.charAt(i)); newClassFileName.append(Integer.toString(this.anonymousCounter)); PackageFragment pkg = (PackageFragment) classFile.getParent(); - return new BinaryType(new ClassFile(pkg, newClassFileName.toString()), typeName); + return new BinaryType(new ClassFile(pkg, DeduplicationUtil.intern(newClassFileName.toString())), typeName); } else if (type.getElementName().equals(typeName)) return type; else @@ -1434,7 +1434,7 @@ protected IJavaElement[] getUnqualifiedMethodHandle(IMethod method, boolean noDo IJavaElement[] result = new IJavaElement[2]; result[0] = ((IType) method.getParent()).getMethod( method.getElementName(), - unqualifiedParameterTypes); + DeduplicationUtil.intern(unqualifiedParameterTypes)); if(hasDollar) { result[1] = result[0]; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java index 56e631640dc..25a0cc7ab59 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java @@ -26,6 +26,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; @@ -954,7 +955,8 @@ public ITypeHierarchy newTypeHierarchy( } @Override public JavaElement resolved(Binding binding) { - ResolvedSourceType resolvedHandle = new ResolvedSourceType(this.getParent(), this.name, new String(binding.computeUniqueKey()), this.getOccurrenceCount()); + ResolvedSourceType resolvedHandle = new ResolvedSourceType(this.getParent(), this.name, + DeduplicationUtil.toString(binding.computeUniqueKey()), this.getOccurrenceCount()); resolvedHandle.localOccurrenceCount = this.localOccurrenceCount; return resolvedHandle; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java index 444cc4852b0..cc319d72589 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java @@ -56,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.JavaModelManager; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; @SuppressWarnings({"rawtypes", "unchecked"}) public class State { @@ -489,7 +490,7 @@ private static AccessRuleSet readRestriction(CompressedReader in) throws IOExcep int problemId = in.readIntWithHint(PROBLEM_IDS); accessRules[i] = manager.getAccessRuleForProblemId(pattern, problemId); } - return new AccessRuleSet(accessRules, in.readByte(), manager.intern(in.readStringUsingDictionary())); + return new AccessRuleSet(accessRules, in.readByte(), DeduplicationUtil.intern(in.readStringUsingDictionary())); } void tagAsNoopBuild() { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java index d4d8fc8bd9f..8ceb199507e 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java @@ -42,6 +42,7 @@ import org.eclipse.jdt.internal.core.SearchableEnvironment; import org.eclipse.jdt.internal.core.SourceTypeElementInfo; import org.eclipse.jdt.internal.core.nd.java.model.BinaryTypeFactory; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.ResourceCompilationUnit; import org.eclipse.jdt.internal.core.util.Util; @@ -222,7 +223,8 @@ protected IType getHandle(IGenericType genericType, ReferenceBinding binding) { classFile = (ClassFile) handle.getParent(); this.infoToHandle.put(genericType, classFile); } - return new ResolvedBinaryType(classFile, classFile.getTypeName(), new String(binding.computeUniqueKey())); + return new ResolvedBinaryType(classFile, classFile.getTypeName(), + DeduplicationUtil.toString(binding.computeUniqueKey())); } else if (genericType instanceof SourceTypeElementInfo) { IType handle = ((SourceTypeElementInfo) genericType).getHandle(); return (IType) ((JavaElement) handle).resolved(binding); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java index 935198ab0a1..2bc0cb99322 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java @@ -67,6 +67,7 @@ import org.eclipse.jdt.internal.compiler.util.Messages; import org.eclipse.jdt.internal.core.*; import org.eclipse.jdt.internal.core.util.ASTNodeFinder; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.HandleFactory; @SuppressWarnings({"rawtypes", "unchecked"}) @@ -504,7 +505,7 @@ private void rememberAllTypes(CompilationUnitDeclaration parsedUnit, org.eclipse if (types != null) { for (int i = 0, length = types.length; i < length; i++) { TypeDeclaration type = types[i]; - rememberWithMemberTypes(type, cu.getType(new String(type.name))); + rememberWithMemberTypes(type, cu.getType(DeduplicationUtil.toString(type.name))); } } if (!includeLocalTypes || (parsedUnit.localTypes.isEmpty() && parsedUnit.functionalExpressions == null)) @@ -539,7 +540,7 @@ private void rememberWithMemberTypes(TypeDeclaration typeDecl, IType typeHandle) if (memberTypes != null) { for (int i = 0, length = memberTypes.length; i < length; i++) { TypeDeclaration memberType = memberTypes[i]; - rememberWithMemberTypes(memberType, typeHandle.getType(new String(memberType.name))); + rememberWithMemberTypes(memberType, typeHandle.getType(DeduplicationUtil.toString(memberType.name))); } } } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DeduplicationUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DeduplicationUtil.java index b25023d4a45..3817764aba3 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DeduplicationUtil.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DeduplicationUtil.java @@ -15,6 +15,8 @@ package org.eclipse.jdt.internal.core.util; +import org.eclipse.jdt.internal.core.JavaElement; + /** Utility to provide deduplication by best effort. **/ public final class DeduplicationUtil { private DeduplicationUtil() { @@ -37,12 +39,33 @@ public static char[] intern(char[] array) { } } + public static String toString(char[] array) { + synchronized (stringSymbols) { + return stringSymbols.add(new String(array)); + } + } + /* * Used as a replacement for String#intern() that could prevent garbage collection of strings on some VMs. */ public static String intern(String s) { + if (s == null) { + return null; + } synchronized (stringSymbols) { return stringSymbols.add(s); } } + + public static String[] intern(String[] a) { + if (a.length == 0) { + return JavaElement.NO_STRINGS; + } + synchronized (stringSymbols) { + for (int j = 0; j < a.length; j++) { + a[j] = a[j] == null ? null : stringSymbols.add(a[j]); + } + return a; + } + } } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java index 3eb134cfcd7..de0f908d170 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java @@ -155,7 +155,7 @@ public Openable createOpenable(String resourcePath, IJavaSearchScope scope) { pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(pkgName); this.packageHandles.put(pkgName, pkgFragment); } - String simpleName= simpleNames[length]; + String simpleName= DeduplicationUtil.intern(simpleNames[length]); if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(simpleName)) { ICompilationUnit unit= pkgFragment.getCompilationUnit(simpleName); return (Openable) unit; @@ -209,10 +209,10 @@ public IJavaElement createElement(Scope scope, int elementPosition, ICompilation IJavaElement parentElement = createElement(scope.parent, elementPosition, unit, existingElements, knownScopes); switch (parentElement.getElementType()) { case IJavaElement.COMPILATION_UNIT : - newElement = ((ICompilationUnit)parentElement).getType(new String(scope.enclosingSourceType().sourceName)); + newElement = ((ICompilationUnit)parentElement).getType(DeduplicationUtil.toString(scope.enclosingSourceType().sourceName)); break; case IJavaElement.TYPE : - newElement = ((IType)parentElement).getType(new String(scope.enclosingSourceType().sourceName)); + newElement = ((IType)parentElement).getType(DeduplicationUtil.toString(scope.enclosingSourceType().sourceName)); break; case IJavaElement.FIELD : case IJavaElement.INITIALIZER : @@ -221,7 +221,7 @@ public IJavaElement createElement(Scope scope, int elementPosition, ICompilation if (member.isBinary()) { return null; } else { - String name = new String(scope.enclosingSourceType().sourceName); + String name = DeduplicationUtil.toString(scope.enclosingSourceType().sourceName); int occurrenceCount = 0; do { newElement = member.getType(name, ++occurrenceCount); @@ -259,7 +259,7 @@ public IJavaElement createElement(Scope scope, int elementPosition, ICompilation switch (field.getKind()) { case AbstractVariableDeclaration.FIELD : case AbstractVariableDeclaration.ENUM_CONSTANT : - newElement = parentType.getField(new String(field.name)); + newElement = parentType.getField(DeduplicationUtil.toString(field.name)); break; case AbstractVariableDeclaration.INITIALIZER : newElement = parentType.getInitializer(occurenceCount); @@ -273,7 +273,7 @@ public IJavaElement createElement(Scope scope, int elementPosition, ICompilation } else { // method element AbstractMethodDeclaration method = methodScope.referenceMethod(); - newElement = parentType.getMethod(new String(method.selector), Util.typeParameterSignatures(method)); + newElement = parentType.getMethod(DeduplicationUtil.toString(method.selector), Util.typeParameterSignatures(method)); if (newElement != null) { knownScopes.put(scope, newElement); } diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java index 626afeb42be..c08a231c9d9 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java @@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.core.BinaryType; import org.eclipse.jdt.internal.core.*; import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; public class ClassFileMatchLocator implements IIndexConstants { @@ -351,13 +352,14 @@ public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType } else { name = method.getSelector(); } - String selector = new String(name); + String selector = DeduplicationUtil.toString(name); char[] methodSignature = binaryMethodSignatures == null ? null : binaryMethodSignatures[i]; if (methodSignature == null) { methodSignature = method.getGenericSignature(); if (methodSignature == null) methodSignature = method.getMethodDescriptor(); } - String[] parameterTypes = CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(methodSignature))); + String[] parameterTypes = DeduplicationUtil.intern(CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(methodSignature)))); + IMethod methodHandle = binaryType.getMethod(selector, parameterTypes); methodHandle = new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey()); locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy); diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java index e2a61b8acf9..535cc5f355d 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java @@ -99,6 +99,7 @@ import org.eclipse.jdt.internal.core.search.indexing.QualifierQuery; import org.eclipse.jdt.internal.core.search.processing.JobManager; import org.eclipse.jdt.internal.core.util.ASTNodeFinder; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.HandleFactory; import org.eclipse.jdt.internal.core.util.Util; @@ -583,7 +584,7 @@ protected IJavaElement createHandle(AbstractMethodDeclaration method, IJavaEleme } } - return createMethodHandle(type, new String(method.selector), parameterTypeSignatures); + return createMethodHandle(type, DeduplicationUtil.toString(method.selector), parameterTypeSignatures); } /* * Create binary method handle @@ -610,7 +611,7 @@ IMethod createBinaryMethodHandle(IType type, char[] methodSelector, char[][] arg parameterTypes[j] = parameterTypeName; } } - return (IMethod) createMethodHandle(type, new String(selector), CharOperation.toStrings(parameterTypes)); + return (IMethod) createMethodHandle(type,DeduplicationUtil.toString(selector), CharOperation.toStrings(parameterTypes)); } } } @@ -641,7 +642,7 @@ protected IJavaElement createHandle(FieldDeclaration fieldDeclaration, TypeDecla switch (fieldDeclaration.getKind()) { case AbstractVariableDeclaration.FIELD : case AbstractVariableDeclaration.ENUM_CONSTANT : - return ((IType) parent).getField(new String(fieldDeclaration.name)); + return ((IType) parent).getField(DeduplicationUtil.toString(fieldDeclaration.name)); } if (type.isBinary()) { // do not return initializer for binary types @@ -677,7 +678,7 @@ protected IJavaElement createHandle(AbstractVariableDeclaration variableDeclarat variableDeclaration.declarationSourceEnd, variableDeclaration.sourceStart, variableDeclaration.sourceEnd, - new String(variableDeclaration.type.resolvedType.signature()), + DeduplicationUtil.toString(variableDeclaration.type.resolvedType.signature()), variableDeclaration.annotations, variableDeclaration.modifiers, isParameter, @@ -3147,15 +3148,15 @@ protected void reportMatching(TypeDeclaration type, IJavaElement parent, int acc // create type handle IJavaElement enclosingElement = parent; if (enclosingElement == null) { - enclosingElement = createTypeHandle(new String(type.name)); + enclosingElement = createTypeHandle(DeduplicationUtil.toString(type.name)); } else if (enclosingElement instanceof IType) { - enclosingElement = ((IType) parent).getType(new String(type.name)); + enclosingElement = ((IType) parent).getType(DeduplicationUtil.toString(type.name)); } else if (enclosingElement instanceof IMember) { IMember member = (IMember) parent; if (member.isBinary()) { enclosingElement = ((IOrdinaryClassFile)this.currentPossibleMatch.openable).getType(); } else { - enclosingElement = member.getType(new String(type.name), occurrenceCount); + enclosingElement = member.getType(DeduplicationUtil.toString(type.name), occurrenceCount); } } if (enclosingElement == null) return; diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java index 6c6dfc316ff..c00b60ea7e6 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java @@ -22,6 +22,7 @@ import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.core.*; +import org.eclipse.jdt.internal.core.util.DeduplicationUtil; import org.eclipse.jdt.internal.core.util.Util; public class PossibleMatch implements ICompilationUnit { @@ -131,7 +132,7 @@ private char[] getQualifiedName() { // get main type name char[] mainTypeName = Util.getNameWithoutJavaLikeExtension(fileName).toCharArray(); CompilationUnit cu = (CompilationUnit) this.openable; - return cu.getType(new String(mainTypeName)).getFullyQualifiedName().toCharArray(); + return cu.getType(DeduplicationUtil.toString(mainTypeName)).getFullyQualifiedName().toCharArray(); } else if (this.openable instanceof ClassFile) { String fileName = getSourceFileName(); if (fileName == NO_SOURCE_FILE_NAME)