Skip to content

Commit e9e5c2f

Browse files
committed
Move methods to util classes
1 parent c73b9d2 commit e9e5c2f

File tree

4 files changed

+85
-39
lines changed

4 files changed

+85
-39
lines changed

CHANGELOG.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ Currently the versioning policy of this project follows [Semantic Versioning v2.
2020
- Fix FP `EI_EXPOSE_REP` when there are multiple immutable assignments ([#3023](https://github.com/spotbugs/spotbugs/issues/3023))
2121
- Fixed false positive `NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR` for Kotlin, handle Kotlin's `Intrinsics.checkNotNullParameter()` ([#3094](https://github.com/spotbugs/spotbugs/issues/3094))
2222

23+
### Added
24+
- New detector `ResourceInMultipleThreadsDetector` and introduced new bug type:
25+
- `AT_UNSAFE_RESOURCE_ACCESS_IN_THREAD` is reported in case of unsafe resource access in multiple threads.
26+
2327
## 4.8.6 - 2024-06-17
2428
### Fixed
2529
- Do not report BC_UNCONFIRMED_CAST for Java 21's type switches when the switch instruction is TABLESWITCH ([#2782](https://github.com/spotbugs/spotbugs/issues/2782))
2630
- Do not throw exception when inspecting empty switch statements ([#2995](https://github.com/spotbugs/spotbugs/issues/2995))
2731
- Adjust priority since relaxed mode reports even `IGNORED_PRIORITY` ([#2994](https://github.com/spotbugs/spotbugs/issues/2994))
2832
- Fix duplicated log4j2 jar in distribution ([#3001](https://github.com/spotbugs/spotbugs/issues/3001))
2933

30-
### Added
31-
- New detector `ResourceInMultipleThreadsDetector` and introduced new bug type:
32-
- `AT_UNSAFE_RESOURCE_ACCESS_IN_THREAD` is reported in case of unsafe resource access in multiple threads.
33-
3434
## 4.8.5 - 2024-05-03
3535
### Fixed
3636
- Fix FP `SING_SINGLETON_GETTER_NOT_SYNCHRONIZED` with eager instances ([#2932](https://github.com/spotbugs/spotbugs/issues/2932))

spotbugs/src/main/java/edu/umd/cs/findbugs/detect/ResourceInMultipleThreadsDetector.java

+6-35
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
package edu.umd.cs.findbugs.detect;
2020

21-
import java.util.Arrays;
2221
import java.util.HashMap;
2322
import java.util.HashSet;
2423
import java.util.Map;
@@ -37,16 +36,15 @@
3736
import edu.umd.cs.findbugs.BugInstance;
3837
import edu.umd.cs.findbugs.BugReporter;
3938
import edu.umd.cs.findbugs.OpcodeStack;
40-
import edu.umd.cs.findbugs.ba.ClassMember;
4139
import edu.umd.cs.findbugs.ba.XField;
4240
import edu.umd.cs.findbugs.ba.XMethod;
4341
import edu.umd.cs.findbugs.bcel.BCELUtil;
4442
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
4543
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
46-
import edu.umd.cs.findbugs.classfile.Global;
4744
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
48-
import edu.umd.cs.findbugs.classfile.engine.bcel.FinallyDuplicatesInfoFactory;
4945
import edu.umd.cs.findbugs.util.BootstrapMethodsUtil;
46+
import edu.umd.cs.findbugs.util.CollectionAnalysis;
47+
import edu.umd.cs.findbugs.util.MethodAnalysis;
5048
import edu.umd.cs.findbugs.util.MutableClasses;
5149

5250
public class ResourceInMultipleThreadsDetector extends OpcodeStackDetector {
@@ -146,17 +144,18 @@ private Optional<MethodDescriptor> getMethodFromBootstrap(JavaClass javaClass, C
146144

147145
private void collectFieldsUsedInThreads(int seen) throws CheckedAnalysisException {
148146
if ((seen == Const.PUTFIELD || seen == Const.PUTSTATIC) && getStack().getStackDepth() > 0
149-
&& !isDuplicatedLocation(getMethodDescriptor(), getPC())
147+
&& !MethodAnalysis.isDuplicatedLocation(getMethodDescriptor(), getPC())
150148
&& methodsUsedInThreads.contains(getMethodDescriptor())) {
151149
OpcodeStack.Item stackItem = getStack().getStackItem(0);
152-
if (stackItem.getReturnValueOf() != null && isSynchronizedCollection(stackItem.getReturnValueOf())) {
150+
if (stackItem.getReturnValueOf() != null && CollectionAnalysis.isSynchronizedCollection(stackItem.getReturnValueOf())) {
153151
synchronizedCollectionTypedFields.add(getXFieldOperand());
154152
} else if (!isAtomicTypedField(getXFieldOperand())
155153
&& !(Const.CONSTRUCTOR_NAME.equals(getMethodName()) || Const.STATIC_INITIALIZER_NAME.equals(getMethodName()))) {
156154
createOrUpdateFieldData(getXFieldOperand(), true, getMethod(), getXMethodOperand());
157155
}
158156
} else if ((seen == Const.INVOKEVIRTUAL || seen == Const.INVOKEINTERFACE || seen == Const.INVOKESPECIAL || seen == Const.INVOKESTATIC)
159-
&& getXMethodOperand() != null && getStack().getStackDepth() > 0 && !isDuplicatedLocation(getMethodDescriptor(), getPC())
157+
&& getXMethodOperand() != null && getStack().getStackDepth() > 0
158+
&& !MethodAnalysis.isDuplicatedLocation(getMethodDescriptor(), getPC())
160159
&& methodsUsedInThreads.contains(getMethodDescriptor())) {
161160
// The field is accessed always be the last item in the stack, because the earlier elements are the arguments
162161
XField xField = getStack().getStackItem(getStack().getStackDepth() - 1).getXField();
@@ -166,34 +165,6 @@ && getXMethodOperand() != null && getStack().getStackDepth() > 0 && !isDuplicate
166165
}
167166
}
168167

169-
/**
170-
* Check if the method is a synchronized collection method.
171-
* @todo: This method should be moved to a utility class when VNA03-J detector is merged
172-
*
173-
* @param classMember the class member
174-
* @return {@code true} if the method is a synchronized collection method, {@code false} otherwise
175-
*/
176-
private static boolean isSynchronizedCollection(ClassMember classMember) {
177-
Set<String> interestingCollectionMethodNames = new HashSet<>(Arrays.asList(
178-
"synchronizedCollection", "synchronizedSet", "synchronizedSortedSet",
179-
"synchronizedNavigableSet", "synchronizedList", "synchronizedMap",
180-
"synchronizedSortedMap", "synchronizedNavigableMap"));
181-
return "java.util.Collections".equals(classMember.getClassName()) && interestingCollectionMethodNames.contains(classMember.getName());
182-
}
183-
184-
/**
185-
* Check if the location is duplicated in the method.
186-
* @todo: This method should be moved to a utility class when VNA03-J detector is merged
187-
*
188-
* @return {@code true} if the location is duplicated in the method, {@code false} otherwise
189-
* @throws CheckedAnalysisException if an error occurs during the analysis
190-
*/
191-
private static boolean isDuplicatedLocation(MethodDescriptor methodDescriptor, int pc) throws CheckedAnalysisException {
192-
FinallyDuplicatesInfoFactory.FinallyDuplicatesInfo methodAnalysis = Global.getAnalysisCache().getMethodAnalysis(
193-
FinallyDuplicatesInfoFactory.FinallyDuplicatesInfo.class, methodDescriptor);
194-
return methodAnalysis.getDuplicates(pc).stream().anyMatch(duplicatePc -> duplicatePc < pc);
195-
}
196-
197168
private boolean isAtomicTypedField(XField xField) {
198169
return xField.getSignature().contains("java/util/concurrent/atomic") || synchronizedCollectionTypedFields.contains(xField);
199170
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package edu.umd.cs.findbugs.util;
2+
3+
import java.util.Arrays;
4+
import java.util.HashSet;
5+
import java.util.Set;
6+
7+
import edu.umd.cs.findbugs.ba.ClassMember;
8+
9+
/**
10+
* Utility class for analyzing collections.
11+
*/
12+
public final class CollectionAnalysis {
13+
14+
private CollectionAnalysis() {
15+
}
16+
17+
/**
18+
* Check if a class member is a synchronized collection.
19+
*
20+
* @param classMember the class member
21+
* @return {@code true} if the class member is a synchronized collection, {@code false} otherwise
22+
*/
23+
public static boolean isSynchronizedCollection(ClassMember classMember) {
24+
Set<String> interestingCollectionMethodNames = new HashSet<>(Arrays.asList(
25+
"synchronizedCollection", "synchronizedSet", "synchronizedSortedSet",
26+
"synchronizedNavigableSet", "synchronizedList", "synchronizedMap",
27+
"synchronizedSortedMap", "synchronizedNavigableMap"));
28+
return "java.util.Collections".equals(classMember.getClassName()) && interestingCollectionMethodNames.contains(classMember.getName());
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* SpotBugs - Find bugs in Java programs
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
*/
18+
19+
package edu.umd.cs.findbugs.util;
20+
21+
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
22+
import edu.umd.cs.findbugs.classfile.Global;
23+
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
24+
import edu.umd.cs.findbugs.classfile.engine.bcel.FinallyDuplicatesInfoFactory;
25+
26+
/**
27+
* Utility class for method analysis.
28+
*/
29+
public final class MethodAnalysis {
30+
31+
private MethodAnalysis() {
32+
}
33+
34+
/**
35+
* Check if the location is duplicated in the method.
36+
*
37+
* @return {@code true} if the location is duplicated in the method, {@code false} otherwise
38+
* @throws CheckedAnalysisException if an error occurs during the analysis
39+
*/
40+
public static boolean isDuplicatedLocation(MethodDescriptor methodDescriptor, int pc) throws CheckedAnalysisException {
41+
FinallyDuplicatesInfoFactory.FinallyDuplicatesInfo methodAnalysis =
42+
Global.getAnalysisCache().getMethodAnalysis(FinallyDuplicatesInfoFactory.FinallyDuplicatesInfo.class, methodDescriptor);
43+
return methodAnalysis.getDuplicates(pc).stream().anyMatch(duplicatePc -> duplicatePc < pc);
44+
}
45+
}

0 commit comments

Comments
 (0)