diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java index 05355ad3d408..2a3c611b1777 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java @@ -150,7 +150,7 @@ public class BytecodeAnalysisIndex extends ScalarIndexExtension { @Override public void save(@NotNull DataOutput out, HMember value) throws IOException { - out.write(value.myBytes); + out.write(value.asBytes()); } @Override @@ -279,7 +279,7 @@ public class BytecodeAnalysisIndex extends ScalarIndexExtension { } private static void writeKey(@NotNull DataOutput out, EKey key, MessageDigest md) throws IOException { - out.write(key.member.hashed(md).myBytes); + out.write(key.member.hashed(md).asBytes()); int rawDirKey = key.negated ? -key.dirKey : key.dirKey; DataInputOutputUtil.writeINT(out, rawDirKey); out.writeBoolean(key.stable); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/HMember.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/HMember.java index f748fbbb8db8..0070b1bcec12 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/HMember.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/HMember.java @@ -19,8 +19,8 @@ import com.intellij.openapi.vfs.CharsetToolkit; import one.util.streamex.IntStreamEx; import org.jetbrains.annotations.NotNull; +import java.nio.ByteBuffer; import java.security.MessageDigest; -import java.util.Arrays; import static com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter.getMessageDigest; @@ -29,41 +29,60 @@ import static com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConve */ public final class HMember implements MemberDescriptor { // how many bytes are taken from class fqn digest - private static final int CLASS_HASH_SIZE = 10; + private static final int CLASS_HASH_SIZE = Long.BYTES+Short.BYTES; // how many bytes are taken from signature digest - private static final int SIGNATURE_HASH_SIZE = 4; + private static final int SIGNATURE_HASH_SIZE = Integer.BYTES; static final int HASH_SIZE = CLASS_HASH_SIZE + SIGNATURE_HASH_SIZE; - @NotNull - final byte[] myBytes; + final long myClassHi; + final short myClassLo; + final int myMethod; HMember(Member method, MessageDigest md) { if (md == null) { md = getMessageDigest(); } byte[] classDigest = md.digest(method.internalClassName.getBytes(CharsetToolkit.UTF8_CHARSET)); + ByteBuffer classBuffer = ByteBuffer.wrap(classDigest); + myClassHi = classBuffer.getLong(); + myClassLo = classBuffer.getShort(); + md.update(method.methodName.getBytes(CharsetToolkit.UTF8_CHARSET)); md.update(method.methodDesc.getBytes(CharsetToolkit.UTF8_CHARSET)); byte[] sigDigest = md.digest(); - myBytes = new byte[HASH_SIZE]; - System.arraycopy(classDigest, 0, myBytes, 0, CLASS_HASH_SIZE); - System.arraycopy(sigDigest, 0, myBytes, CLASS_HASH_SIZE, SIGNATURE_HASH_SIZE); + myMethod = ByteBuffer.wrap(sigDigest).getInt(); } public HMember(@NotNull byte[] bytes) { - myBytes = bytes; + ByteBuffer buffer = ByteBuffer.wrap(bytes); + myClassHi = buffer.getLong(); + myClassLo = buffer.getShort(); + myMethod = buffer.getInt(); + } + + @NotNull + byte[] asBytes() { + ByteBuffer bytes = ByteBuffer.allocate(HASH_SIZE); + bytes.putLong(myClassHi).putShort(myClassLo).putInt(myMethod); + return bytes.array(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - return Arrays.equals(myBytes, ((HMember)o).myBytes); + HMember that = (HMember)o; + return that.myClassHi == myClassHi && that.myClassLo == myClassLo && that.myMethod == myMethod; } @Override public int hashCode() { - return Arrays.hashCode(myBytes); + // Must work as Arrays.hashCode(asBytes()) to preserve compatibility with old caches + int result = 1; + for (int i = Long.BYTES - 1; i >= 0; i--) result = result * 31 + (byte)((myClassHi >>> (i * 8)) & 0xFF); + for (int i = Short.BYTES - 1; i >= 0; i--) result = result * 31 + (byte)((myClassLo >>> (i * 8)) & 0xFF); + for (int i = Integer.BYTES - 1; i >= 0; i--) result = result * 31 + (byte)((myMethod >>> (i * 8)) & 0xFF); + return result; } @NotNull @@ -73,7 +92,7 @@ public final class HMember implements MemberDescriptor { } public String toString() { - return bytesToString(myBytes); + return bytesToString(asBytes()); } static String bytesToString(byte[] key) {