From 962687709bc232c6ae44a7c57f8742e9223b700c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Coet?= Date: Thu, 15 Oct 2026 11:34:32 +0200 Subject: [PATCH 1/2] Do not allocate lambdas on cache hits in JSema --- .../main/java/org/sonar/java/model/JSema.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/java-frontend/src/main/java/org/sonar/java/model/JSema.java b/java-frontend/src/main/java/org/sonar/java/model/JSema.java index 313ef260d2d..4e3b28e0522 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/JSema.java +++ b/java-frontend/src/main/java/org/sonar/java/model/JSema.java @@ -56,7 +56,11 @@ public final class JSema implements Sema { } public JType type(ITypeBinding typeBinding) { - return types.computeIfAbsent(typeBinding, k -> new JType(this, JType.normalize(typeBinding))); + JType cached = types.get(typeBinding); + if (cached != null) { + return cached; + } + return types.computeIfAbsent(typeBinding, k -> new JType(this, JType.normalize(k))); } List types(ITypeBinding[] typeBindings) { @@ -74,14 +78,26 @@ public Symbol packageSymbol(@Nullable IPackageBinding packageBinding) { if (packageBinding == null) { return Symbol.ROOT_PACKAGE; } + JSymbol cached = symbols.get(packageBinding); + if (cached != null) { + return cached; + } return symbols.computeIfAbsent(packageBinding, k -> new JPackageSymbol(this, (IPackageBinding) k)); } public JTypeSymbol typeSymbol(ITypeBinding typeBinding) { + JTypeSymbol cached = (JTypeSymbol) symbols.get(typeBinding); + if (cached != null) { + return cached; + } return (JTypeSymbol) symbols.computeIfAbsent(typeBinding, k -> new JTypeSymbol(this, JType.normalize((ITypeBinding) k))); } public JMethodSymbol methodSymbol(IMethodBinding methodBinding) { + JMethodSymbol cached = (JMethodSymbol) symbols.get(methodBinding); + if (cached != null) { + return cached; + } return (JMethodSymbol) symbols.computeIfAbsent(methodBinding, k -> new JMethodSymbol(this, (IMethodBinding) k)); } @@ -95,10 +111,18 @@ public JInitializerBlockSymbol staticInitializerBlockSymbol(JTypeSymbol owner) { public JVariableSymbol variableSymbol(IVariableBinding variableBinding) { + JVariableSymbol cached = (JVariableSymbol) symbols.get(variableBinding); + if (cached != null) { + return cached; + } return (JVariableSymbol) symbols.computeIfAbsent(variableBinding, k -> new JVariableSymbol(this, (IVariableBinding) k)); } JSymbolMetadata.JAnnotationInstance annotation(IAnnotationBinding annotationBinding) { + JSymbolMetadata.JAnnotationInstance cached = annotations.get(annotationBinding); + if (cached != null) { + return cached; + } return annotations.computeIfAbsent(annotationBinding, k -> new JSymbolMetadata.JAnnotationInstance(this, k)); } @@ -117,6 +141,10 @@ static IBinding declarationBinding(IBinding binding) { @Override public Type getClassType(String fullyQualifiedName) { + Type cached = nameToTypeCache.get(fullyQualifiedName); + if (cached != null) { + return cached; + } return nameToTypeCache.computeIfAbsent(fullyQualifiedName, t -> { ITypeBinding typeBinding = resolveType(t); return typeBinding != null ? type(typeBinding) : Type.UNKNOWN; From 1cab89bdfbb9b049876c1ae429d64a3e98e2a26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Coet?= Date: Thu, 15 Oct 2026 13:33:14 +0200 Subject: [PATCH 2/2] Apply Gitar review comments --- .../src/main/java/org/sonar/java/model/JSema.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/java-frontend/src/main/java/org/sonar/java/model/JSema.java b/java-frontend/src/main/java/org/sonar/java/model/JSema.java index 4e3b28e0522..4045f8d1db5 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/JSema.java +++ b/java-frontend/src/main/java/org/sonar/java/model/JSema.java @@ -102,11 +102,19 @@ public JMethodSymbol methodSymbol(IMethodBinding methodBinding) { } public JInitializerBlockSymbol initializerBlockSymbol(JTypeSymbol owner) { - return initializerBlockSymbols.computeIfAbsent(owner, k -> new JInitializerBlockSymbol(owner, false)); + JInitializerBlockSymbol cached = initializerBlockSymbols.get(owner); + if (cached != null) { + return cached; + } + return initializerBlockSymbols.computeIfAbsent(owner, k -> new JInitializerBlockSymbol(k, false)); } public JInitializerBlockSymbol staticInitializerBlockSymbol(JTypeSymbol owner) { - return staticInitializerBlockSymbols.computeIfAbsent(owner, k -> new JInitializerBlockSymbol(owner, true)); + JInitializerBlockSymbol cached = staticInitializerBlockSymbols.get(owner); + if (cached != null) { + return cached; + } + return staticInitializerBlockSymbols.computeIfAbsent(owner, k -> new JInitializerBlockSymbol(k, true)); }