From 4a8a53e634f7a1b7f38a8ea236202fb17e1845ba Mon Sep 17 00:00:00 2001
From: Shai Almog <67850168+shai-almog@users.noreply.github.com>
Date: Wed, 14 Jan 2026 20:15:17 +0200
Subject: [PATCH 1/9] Fixed NN_NAKED_NOTIFY Spotbugs Issues (#4417)
---
.github/scripts/generate-quality-report.py | 3 +++
CodenameOne/src/com/codename1/capture/Capture.java | 2 +-
CodenameOne/src/com/codename1/components/WebBrowser.java | 2 +-
.../com/codename1/impl/CodenameOneImplementation.java | 6 +-----
CodenameOne/src/com/codename1/io/NetworkManager.java | 4 ++--
CodenameOne/src/com/codename1/ui/Display.java | 4 ++--
CodenameOne/src/com/codename1/ui/RunnableWrapper.java | 2 +-
.../ui/html/AsyncDocumentRequestHandlerImpl.java | 2 +-
maven/core-unittests/spotbugs-exclude.xml | 9 +++++++++
9 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py
index 7855cad769..0f46f75376 100755
--- a/.github/scripts/generate-quality-report.py
+++ b/.github/scripts/generate-quality-report.py
@@ -815,6 +815,7 @@ def main() -> None:
"NM_CONFUSING",
"NM_FIELD_NAMING_CONVENTION",
"NM_METHOD_NAMING_CONVENTION",
+ "NN_NAKED_NOTIFY",
"NO_NOTIFY_NOT_NOTIFYALL",
"NP_LOAD_OF_KNOWN_NULL_VALUE",
"NP_BOOLEAN_RETURN_NULL",
@@ -851,6 +852,8 @@ def _is_exempt(f: Finding) -> bool:
return True
if f.rule == "URF_UNREAD_FIELD" and "GridBagLayoutInfo" in loc:
return True
+ if f.rule == "NN_NAKED_NOTIFY" and "Display.java" in loc:
+ return True
return False
diff --git a/CodenameOne/src/com/codename1/capture/Capture.java b/CodenameOne/src/com/codename1/capture/Capture.java
index 4b65da9637..8571073ce2 100644
--- a/CodenameOne/src/com/codename1/capture/Capture.java
+++ b/CodenameOne/src/com/codename1/capture/Capture.java
@@ -257,8 +257,8 @@ public void actionPerformed(ActionEvent evt) {
} else {
url = (String) evt.getSource();
}
- completed = true;
synchronized (this) {
+ completed = true;
this.notifyAll();
}
}
diff --git a/CodenameOne/src/com/codename1/components/WebBrowser.java b/CodenameOne/src/com/codename1/components/WebBrowser.java
index 50f4791d8b..0067d89f00 100644
--- a/CodenameOne/src/com/codename1/components/WebBrowser.java
+++ b/CodenameOne/src/com/codename1/components/WebBrowser.java
@@ -154,8 +154,8 @@ protected void readResponse(InputStream input) throws IOException {
if (callback != null) {
callback.streamReady(input, docInfo);
} else {
- response[0] = input;
synchronized (LOCK) {
+ response[0] = input;
LOCK.notifyAll();
}
}
diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java
index 0fdaad117e..b329e3adca 100644
--- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java
+++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java
@@ -7177,13 +7177,9 @@ protected final void pushReceived(String data) {
* Sets the frequency for polling the server in case of polling based push notification
*
* @param freq the frequency in milliseconds
+ * @deprecated we no longer support push polling
*/
public void setPollingFrequency(int freq) {
- if (callback != null && pollingThreadRunning) {
- synchronized (callback) {
- callback.notifyAll();
- }
- }
}
/**
diff --git a/CodenameOne/src/com/codename1/io/NetworkManager.java b/CodenameOne/src/com/codename1/io/NetworkManager.java
index a96c460b8f..438917d40e 100644
--- a/CodenameOne/src/com/codename1/io/NetworkManager.java
+++ b/CodenameOne/src/com/codename1/io/NetworkManager.java
@@ -330,8 +330,8 @@ public void shutdown() {
}
}
}
- networkThreads = null;
synchronized (LOCK) {
+ networkThreads = null;
LOCK.notifyAll();
}
@@ -970,10 +970,10 @@ public void run() {
if (!runCurrentRequest(currentRequest)) {
continue;
}
- currentRequest = null;
// wakeup threads waiting for the completion of this network operation
synchronized (LOCK) {
+ currentRequest = null;
LOCK.notifyAll();
}
} else {
diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java
index 45d8ebd0b5..d9c1db5ac5 100644
--- a/CodenameOne/src/com/codename1/ui/Display.java
+++ b/CodenameOne/src/com/codename1/ui/Display.java
@@ -506,9 +506,8 @@ public static void init(Object m) {
* Notice that minimize (being a Codename One method) MUST be invoked before invoking this method!
*/
public static void deinitialize() {
-
- INSTANCE.codenameOneRunning = false;
synchronized (lock) {
+ INSTANCE.codenameOneRunning = false;
lock.notifyAll();
}
}
@@ -4684,6 +4683,7 @@ public String getDatabasePath(String databaseName) {
* Sets the frequency for polling the server in case of polling based push notification
*
* @param freq the frequency in milliseconds
+ * @deprecated we no longer support push polling
*/
public void setPollingFrequency(int freq) {
impl.setPollingFrequency(freq);
diff --git a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java
index 985534c41c..44c4643254 100644
--- a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java
+++ b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java
@@ -106,8 +106,8 @@ public void run() {
switch (type) {
case 0:
internal.run();
- done = true;
synchronized (Display.lock) {
+ done = true;
Display.lock.notifyAll();
}
break;
diff --git a/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java
index 15b65a0e5d..f4c02f4b74 100644
--- a/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java
+++ b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java
@@ -155,8 +155,8 @@ protected void readResponse(InputStream input) throws IOException {
if (callback != null) {
callback.streamReady(input, docInfo);
} else {
- response[0] = input;
synchronized (LOCK) {
+ response[0] = input;
LOCK.notifyAll();
}
}
diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml
index 83d432d54b..221cdb8d49 100644
--- a/maven/core-unittests/spotbugs-exclude.xml
+++ b/maven/core-unittests/spotbugs-exclude.xml
@@ -152,6 +152,15 @@
+
+
+
+
+
+
From da736bfdaf969b32ac41ed80cac5ad915a0a1040 Mon Sep 17 00:00:00 2001
From: Shai Almog <67850168+shai-almog@users.noreply.github.com>
Date: Wed, 14 Jan 2026 20:32:21 +0200
Subject: [PATCH 2/9] Fix SpotBugs findings and enforce rules (#4414)
---
.github/scripts/generate-quality-report.py | 6 +++
.../codename1/charts/views/PieSegment.java | 7 ++--
.../codename1/charts/views/RadarChart.java | 5 ++-
.../com/codename1/io/MultipartRequest.java | 10 ++---
.../com/codename1/io/rest/RequestBuilder.java | 5 ++-
.../codename1/properties/PropertyIndex.java | 8 ++--
.../properties/PropertyXMLElement.java | 24 +++++++++--
.../src/com/codename1/ui/geom/Rectangle.java | 29 --------------
.../ui/layouts/mig/ConstraintParser.java | 2 +-
.../codename1/ui/layouts/mig/UnitValue.java | 40 ++++++++++++++++---
.../codename1/ui/plaf/RoundRectBorder.java | 2 +-
11 files changed, 83 insertions(+), 55 deletions(-)
diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py
index 0f46f75376..a3d3c57dfa 100755
--- a/.github/scripts/generate-quality-report.py
+++ b/.github/scripts/generate-quality-report.py
@@ -823,6 +823,12 @@ def main() -> None:
"REC_CATCH_EXCEPTION",
"RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
"RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT",
+ "INT_VACUOUS_COMPARISON",
+ "DM_STRING_TOSTRING",
+ "HE_HASHCODE_USE_OBJECT_EQUALS",
+ "IM_BAD_CHECK_FOR_ODD",
+ "IT_NO_SUCH_ELEMENT",
+ "FL_FLOATS_AS_LOOP_COUNTERS",
"UI_INHERITANCE_UNSAFE_GETRESOURCE",
"URF_UNREAD_FIELD",
"URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD",
diff --git a/CodenameOne/src/com/codename1/charts/views/PieSegment.java b/CodenameOne/src/com/codename1/charts/views/PieSegment.java
index caf8bee97e..756bba6087 100644
--- a/CodenameOne/src/com/codename1/charts/views/PieSegment.java
+++ b/CodenameOne/src/com/codename1/charts/views/PieSegment.java
@@ -52,9 +52,10 @@ public boolean isInSegment(double angle) {
double cAngle = angle % 360;
double startAngle = mStartAngle;
double stopAngle = mEndAngle;
- while (stopAngle > 360) {
- startAngle -= 360;
- stopAngle -= 360;
+ if (stopAngle > 360) {
+ int rotations = (int) Math.floor(stopAngle / 360d);
+ startAngle -= 360 * rotations;
+ stopAngle -= 360 * rotations;
}
return cAngle >= startAngle && cAngle <= stopAngle;
}
diff --git a/CodenameOne/src/com/codename1/charts/views/RadarChart.java b/CodenameOne/src/com/codename1/charts/views/RadarChart.java
index 7adb92969e..7bc8de3671 100644
--- a/CodenameOne/src/com/codename1/charts/views/RadarChart.java
+++ b/CodenameOne/src/com/codename1/charts/views/RadarChart.java
@@ -112,8 +112,9 @@ public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint
paint.setColor(ColorUtil.GRAY);
float thisRad = (float) Math.toRadians(90 - currentAngle);
float nextRad = (float) Math.toRadians(90 - (currentAngle + angle));
- for (double level = 0; level <= 1d; level += decCoef) { // PMD Fix: DontUseFloatTypeForLoopIndices switched to double
- float levelFactor = (float) level;
+ int levelSteps = (int) Math.round(1d / decCoef);
+ for (int level = 0; level <= levelSteps; level++) {
+ float levelFactor = (float) (level * decCoef);
float thisX = (float) (centerX - Math.sin(thisRad) * radius * levelFactor);
float thisY = (float) (centerY - Math.cos(thisRad) * radius * levelFactor);
float nextX = (float) (centerX - Math.sin(nextRad) * radius * levelFactor);
diff --git a/CodenameOne/src/com/codename1/io/MultipartRequest.java b/CodenameOne/src/com/codename1/io/MultipartRequest.java
index 7a383cd34a..ff026cc1ef 100644
--- a/CodenameOne/src/com/codename1/io/MultipartRequest.java
+++ b/CodenameOne/src/com/codename1/io/MultipartRequest.java
@@ -269,9 +269,9 @@ protected long calculateContentLength() {
length += key.length();
if (ignoreEncoding.contains(key)) {
try {
- length += value.toString().getBytes("UTF-8").length;
+ length += ((String) value).getBytes("UTF-8").length;
} catch (UnsupportedEncodingException ex) {
- length += StringUtil.getBytes(value.toString()).length;
+ length += StringUtil.getBytes((String) value).length;
}
} else {
if (base64Binaries) {
@@ -287,9 +287,9 @@ protected long calculateContentLength() {
length += key.length();
if (ignoreEncoding.contains(key)) {
try {
- length += s.toString().getBytes("UTF-8").length;
+ length += s.getBytes("UTF-8").length;
} catch (UnsupportedEncodingException ex) {
- length += StringUtil.getBytes(value.toString()).length;
+ length += StringUtil.getBytes(s).length;
}
} else {
if (base64Binaries) {
@@ -534,4 +534,4 @@ public int hashCode() {
result = 31 * result + (args != null ? args.hashCode() : 0);
return result;
}
-}
\ No newline at end of file
+}
diff --git a/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java b/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java
index a143338ed6..4294da0491 100644
--- a/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java
+++ b/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java
@@ -48,6 +48,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* This class is used to build, invoke the http request and to get the http
@@ -249,8 +250,8 @@ public RequestBuilder queryParam(String key, String[] values) {
*/
public RequestBuilder header(String key, String value) {
checkFetched();
- // .toString() is used to trigger an NPE early for null headers
- headers.put(key.toString(), value.toString());
+ headers.put(Objects.requireNonNull(key, "Header key cannot be null"),
+ Objects.requireNonNull(value, "Header value cannot be null"));
return this;
}
diff --git a/CodenameOne/src/com/codename1/properties/PropertyIndex.java b/CodenameOne/src/com/codename1/properties/PropertyIndex.java
index 9ed9fe4770..1956334faf 100644
--- a/CodenameOne/src/com/codename1/properties/PropertyIndex.java
+++ b/CodenameOne/src/com/codename1/properties/PropertyIndex.java
@@ -55,6 +55,7 @@
import java.util.List;
import java.util.Map;
import java.util.Enumeration;
+import java.util.NoSuchElementException;
/**
* Maps the properties that are in a class/object and provides access to them so tools such as ORM
@@ -198,9 +199,10 @@ public void remove() {
}
public PropertyBase next() {
- int i = off;
- off++;
- return properties[i];
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return properties[off++];
}
};
}
diff --git a/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java b/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java
index 54601eed8f..d885a27ae6 100644
--- a/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java
+++ b/CodenameOne/src/com/codename1/properties/PropertyXMLElement.java
@@ -29,6 +29,8 @@
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Vector;
/**
@@ -295,7 +297,21 @@ public boolean isEmpty() {
@Override
public int hashCode() {
- return parent.hashCode();
+ return Objects.hash(parent, parentElement, index);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof PropertyXMLElement)) {
+ return false;
+ }
+ PropertyXMLElement other = (PropertyXMLElement) obj;
+ return index == other.index
+ && Objects.equals(parent, other.parent)
+ && Objects.equals(parentElement, other.parentElement);
}
@Override
@@ -330,8 +346,10 @@ public boolean hasNext() {
@Override
public Element next() {
- offset++;
- return getChildAt(index);
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return getChildAt(offset++);
}
@Override
diff --git a/CodenameOne/src/com/codename1/ui/geom/Rectangle.java b/CodenameOne/src/com/codename1/ui/geom/Rectangle.java
index 292db87755..b84a036fa9 100644
--- a/CodenameOne/src/com/codename1/ui/geom/Rectangle.java
+++ b/CodenameOne/src/com/codename1/ui/geom/Rectangle.java
@@ -188,16 +188,6 @@ public static void intersection(int rrX, int rrY, int rrW, int rrH, int rtx1, in
tx2 -= tx1;
ty2 -= ty1;
- // tx2,ty2 will never overflow (they will never be
- // larger than the smallest of the two source w,h)
- // they might underflow, though...
- if (tx2 < Integer.MIN_VALUE) {
- tx2 = Integer.MIN_VALUE;
- }
- if (ty2 < Integer.MIN_VALUE) {
- ty2 = Integer.MIN_VALUE;
- }
-
dest.x = tx1;
dest.y = ty1;
dest.size.setWidth(tx2);
@@ -422,16 +412,6 @@ public Rectangle intersection(int rX, int rY, int rW, int rH) {
}
tx2 -= tx1;
ty2 -= ty1;
- // tx2,ty2 will never overflow (they will never be
- // larger than the smallest of the two source w,h)
- // they might underflow, though...
- if (tx2 < Integer.MIN_VALUE) {
- tx2 = Integer.MIN_VALUE;
- }
- if (ty2 < Integer.MIN_VALUE) {
- ty2 = Integer.MIN_VALUE;
- }
-
return new Rectangle(tx1, ty1, tx2, ty2);
}
@@ -462,15 +442,6 @@ public void intersection(Rectangle input, Rectangle output) {
}
tx2 -= tx1;
ty2 -= ty1;
- // tx2,ty2 will never overflow (they will never be
- // larger than the smallest of the two source w,h)
- // they might underflow, though...
- if (tx2 < Integer.MIN_VALUE) {
- tx2 = Integer.MIN_VALUE;
- }
- if (ty2 < Integer.MIN_VALUE) {
- ty2 = Integer.MIN_VALUE;
- }
tx2 = Math.max(0, tx2);
ty2 = Math.max(0, ty2);
output.setBounds(tx1, ty1, tx2, ty2);
diff --git a/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java b/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java
index c6128d94f1..3c3313e7f7 100644
--- a/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java
+++ b/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java
@@ -969,7 +969,7 @@ public static UnitValue[] parseInsets(String s, boolean acceptPanel) {
String[] insS = toTrimmedTokens(s, ' ');
UnitValue[] ins = new UnitValue[4];
for (int j = 0; j < 4; j++) {
- UnitValue insSz = parseUnitValue(insS[j < insS.length ? j : insS.length - 1], UnitValue.ZERO, j % 2 == 1);
+ UnitValue insSz = parseUnitValue(insS[j < insS.length ? j : insS.length - 1], UnitValue.ZERO, (j & 1) != 0);
ins[j] = insSz != null ? insSz : PlatformDefaults.getPanelInsets(j);
}
return ins;
diff --git a/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java b/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java
index ef83274fff..cb1e34268f 100644
--- a/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java
+++ b/CodenameOne/src/com/codename1/ui/layouts/mig/UnitValue.java
@@ -35,8 +35,10 @@
import com.codename1.util.MathUtil;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Objects;
public final class UnitValue {
/**
@@ -617,7 +619,33 @@ public String getConstraintString() {
return LayoutUtil.getCCString(this);
}
- public int hashCode() {
- return (int) (value * 12345) + (oper >>> 5) + unit >>> 17;
- }
-}
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + Float.floatToIntBits(value);
+ result = 31 * result + unit;
+ result = 31 * result + oper;
+ result = 31 * result + (isHor ? 1 : 0);
+ result = 31 * result + (unitStr != null ? unitStr.hashCode() : 0);
+ result = 31 * result + (linkId != null ? linkId.hashCode() : 0);
+ result = 31 * result + Arrays.hashCode(subUnits);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof UnitValue)) {
+ return false;
+ }
+ UnitValue other = (UnitValue) obj;
+ return Float.compare(value, other.value) == 0
+ && unit == other.unit
+ && oper == other.oper
+ && isHor == other.isHor
+ && Objects.equals(unitStr, other.unitStr)
+ && Objects.equals(linkId, other.linkId)
+ && Arrays.equals(subUnits, other.subUnits);
+ }
+}
diff --git a/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java b/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java
index 91d3b46ba0..4d22101d86 100644
--- a/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java
+++ b/CodenameOne/src/com/codename1/ui/plaf/RoundRectBorder.java
@@ -886,7 +886,7 @@ private GeneralPath createShape(int shapeW, int shapeH) {
x += strokePx / 2f;
y += strokePx / 2f;
- if (strokePx % 2 == 1) {
+ if ((strokePx & 1) != 0) {
x += 0.5f;
y += 0.5f;
}
From 48978034c23311d7ddcdb2753439f0b1e5597689 Mon Sep 17 00:00:00 2001
From: Shai Almog <67850168+shai-almog@users.noreply.github.com>
Date: Thu, 15 Jan 2026 04:09:25 +0200
Subject: [PATCH 3/9] Fix SpotBugs warnings and tighten gates (#4418)
---
.github/scripts/generate-quality-report.py | 5 +++++
.../src/com/codename1/facebook/FacebookRESTService.java | 5 ++++-
.../src/com/codename1/io/gzip/DeflaterOutputStream.java | 2 +-
CodenameOne/src/com/codename1/location/LocationManager.java | 5 +++--
CodenameOne/src/com/codename1/properties/InstantUI.java | 2 +-
CodenameOne/src/com/codename1/ui/BrowserComponent.java | 2 +-
CodenameOne/src/com/codename1/ui/html/HTMLComponent.java | 6 +++---
CodenameOne/src/com/codename1/ui/plaf/UIManager.java | 1 -
CodenameOne/src/com/codename1/util/TBigInteger.java | 2 +-
9 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py
index a3d3c57dfa..9084a2a20f 100755
--- a/.github/scripts/generate-quality-report.py
+++ b/.github/scripts/generate-quality-report.py
@@ -763,6 +763,7 @@ def main() -> None:
if spotbugs:
forbidden_rules = {
"NP_ALWAYS_NULL",
+ "NP_NULL_PARAM_DEREF",
"RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE",
"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR",
@@ -772,6 +773,7 @@ def main() -> None:
"IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD",
"LI_LAZY_INIT_STATIC",
"RpC_REPEATED_CONDITIONAL_TEST",
+ "NS_NON_SHORT_CIRCUIT",
"ES_COMPARING_PARAMETER_STRING_WITH_EQ",
"FE_FLOATING_POINT_EQUALITY",
"FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER",
@@ -787,7 +789,9 @@ def main() -> None:
"EQ_DOESNT_OVERRIDE_EQUALS",
"CO_COMPARETO_INCORRECT_FLOATING",
"DL_SYNCHRONIZATION_ON_SHARED_CONSTANT",
+ "SSD_DO_NOT_USE_INSTANCE_LOCK_ON_SHARED_STATIC_DATA",
"DLS_DEAD_LOCAL_STORE",
+ "DLS_DEAD_LOCAL_STORE_OF_NULL",
"DM_NUMBER_CTOR",
"DMI_INVOKING_TOSTRING_ON_ARRAY",
"EC_NULL_ARG",
@@ -819,6 +823,7 @@ def main() -> None:
"NO_NOTIFY_NOT_NOTIFYALL",
"NP_LOAD_OF_KNOWN_NULL_VALUE",
"NP_BOOLEAN_RETURN_NULL",
+ "RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN",
"REFLC_REFLECTION_MAY_INCREASE_ACCESSIBILITY_OF_CLASS",
"REC_CATCH_EXCEPTION",
"RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
diff --git a/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java b/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java
index f9c8ad68d1..82a6b05926 100644
--- a/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java
+++ b/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java
@@ -239,8 +239,11 @@ public void numericToken(double tok) {
}
public void keyValue(String key, String value) {
+ if (key == null) {
+ return;
+ }
//make sure value is not null to prevent NPE
- if (key != null && value == null) {
+ if (value == null) {
value = "";
}
getCurrent().put(key, value);
diff --git a/CodenameOne/src/com/codename1/io/gzip/DeflaterOutputStream.java b/CodenameOne/src/com/codename1/io/gzip/DeflaterOutputStream.java
index eb3a2733a9..71dcc2f4a2 100644
--- a/CodenameOne/src/com/codename1/io/gzip/DeflaterOutputStream.java
+++ b/CodenameOne/src/com/codename1/io/gzip/DeflaterOutputStream.java
@@ -84,7 +84,7 @@ public void write(int b) throws IOException {
public void write(byte[] b, int off, int len) throws IOException {
if (deflater.finished()) {
throw new IOException("finished");
- } else if (off < 0 | len < 0 | off + len > b.length) {
+ } else if (off < 0 || len < 0 || off + len > b.length) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
} else {
diff --git a/CodenameOne/src/com/codename1/location/LocationManager.java b/CodenameOne/src/com/codename1/location/LocationManager.java
index cb29be9d96..1cd246771c 100644
--- a/CodenameOne/src/com/codename1/location/LocationManager.java
+++ b/CodenameOne/src/com/codename1/location/LocationManager.java
@@ -52,6 +52,7 @@ public abstract class LocationManager {
public static final int OUT_OF_SERVICE = 1;
public static final int TEMPORARILY_UNAVAILABLE = 2;
private static LocationListener listener;
+ private static final Object LISTENER_LOCK = new Object();
private LocationRequest request;
private static Class backgroundlistener;
private int status = TEMPORARILY_UNAVAILABLE;
@@ -198,7 +199,7 @@ protected LocationListener getLocationListener() {
* from getting updates
*/
public void setLocationListener(final LocationListener l) {
- synchronized (this) {
+ synchronized (LISTENER_LOCK) {
if (listener != null) {
clearListener();
request = null;
@@ -243,7 +244,7 @@ protected Class getBackgroundLocationListener() {
* try to create an instance and invoke the locationUpdated method
*/
public void setBackgroundLocationListener(Class locationListener) {
- synchronized (this) {
+ synchronized (LISTENER_LOCK) {
if (backgroundlistener != null) {
clearBackgroundListener();
}
diff --git a/CodenameOne/src/com/codename1/properties/InstantUI.java b/CodenameOne/src/com/codename1/properties/InstantUI.java
index 6802aca598..b13fc8e6c1 100644
--- a/CodenameOne/src/com/codename1/properties/InstantUI.java
+++ b/CodenameOne/src/com/codename1/properties/InstantUI.java
@@ -81,7 +81,7 @@ public void excludeProperties(PropertyBase... exclude) {
* @return true if the property was excluded from the GUI
*/
public boolean isExcludedProperty(PropertyBase exclude) {
- return exclude.getClientProperty("cn1$excludeFromUI") == Boolean.TRUE;
+ return Boolean.TRUE.equals(exclude.getClientProperty("cn1$excludeFromUI"));
}
/**
diff --git a/CodenameOne/src/com/codename1/ui/BrowserComponent.java b/CodenameOne/src/com/codename1/ui/BrowserComponent.java
index afc234a438..eeefc7bd05 100644
--- a/CodenameOne/src/com/codename1/ui/BrowserComponent.java
+++ b/CodenameOne/src/com/codename1/ui/BrowserComponent.java
@@ -1601,7 +1601,7 @@ public void putClientProperty(String key, Object value) {
* @return true if debug mode was activated
*/
public boolean isDebugMode() {
- return getClientProperty("BrowserComponent.firebug") == Boolean.TRUE;
+ return Boolean.TRUE.equals(getClientProperty("BrowserComponent.firebug"));
}
/**
diff --git a/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java b/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java
index 1fe1a7aedd..5be218e7d2 100644
--- a/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java
+++ b/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java
@@ -463,13 +463,13 @@ public HTMLComponent(DocumentRequestHandler handler) {
* @param font The actual Codename One font object
*/
public static void addFont(String fontKey, Font font) {
- if (fontKey != null) {
- fontKey = fontKey.toLowerCase();
- } else {
+ if (fontKey == null) {
if (font.getCharset() != null) {
throw new IllegalArgumentException("Font key must be non-null for bitmap fonts");
}
+ throw new IllegalArgumentException("Font key must be non-null");
}
+ fontKey = fontKey.toLowerCase();
fonts.put(fontKey, new HTMLFont(fontKey, font));
}
diff --git a/CodenameOne/src/com/codename1/ui/plaf/UIManager.java b/CodenameOne/src/com/codename1/ui/plaf/UIManager.java
index 98c405b3ef..c88228a367 100644
--- a/CodenameOne/src/com/codename1/ui/plaf/UIManager.java
+++ b/CodenameOne/src/com/codename1/ui/plaf/UIManager.java
@@ -1901,7 +1901,6 @@ Style createStyle(String id, String prefix, boolean selected) {
style = new Style(getComponentStyle(baseStyle));
}
} else {
- baseStyle = null;
if (selected) {
style = new Style(defaultSelectedStyle);
} else {
diff --git a/CodenameOne/src/com/codename1/util/TBigInteger.java b/CodenameOne/src/com/codename1/util/TBigInteger.java
index 8f2a34baf5..1581e4499d 100644
--- a/CodenameOne/src/com/codename1/util/TBigInteger.java
+++ b/CodenameOne/src/com/codename1/util/TBigInteger.java
@@ -1240,7 +1240,7 @@ public TBigInteger modPow(TBigInteger exponent, TBigInteger m) {
}
TBigInteger base = this;
- if (m.isOne() | (exponent.sign > 0 & base.sign == 0)) {
+ if (m.isOne() || (exponent.sign > 0 && base.sign == 0)) {
return TBigInteger.ZERO;
}
if (exponent.sign == 0) {
From 4efa5650366dcbb187c04240e562596771189d27 Mon Sep 17 00:00:00 2001
From: Shai Almog <67850168+shai-almog@users.noreply.github.com>
Date: Thu, 15 Jan 2026 17:14:30 +0200
Subject: [PATCH 4/9] tail end of big spotbugs issues (#4419)
---
.github/scripts/generate-quality-report.py | 4 ++
.../impl/CodenameOneImplementation.java | 13 +++---
.../com/codename1/impl/CodenameOneThread.java | 10 ++++-
.../com/codename1/testing/DeviceRunner.java | 16 +++++---
maven/core-unittests/spotbugs-exclude.xml | 41 +++++++++++++++++++
5 files changed, 69 insertions(+), 15 deletions(-)
diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py
index 9084a2a20f..f6b4cb24a2 100755
--- a/.github/scripts/generate-quality-report.py
+++ b/.github/scripts/generate-quality-report.py
@@ -778,6 +778,7 @@ def main() -> None:
"FE_FLOATING_POINT_EQUALITY",
"FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER",
"ICAST_IDIV_CAST_TO_DOUBLE",
+ "ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT",
"SA_FIELD_SELF_ASSIGNMENT",
"UC_USELESS_CONDITION",
"UC_USELESS_OBJECT",
@@ -824,6 +825,7 @@ def main() -> None:
"NP_LOAD_OF_KNOWN_NULL_VALUE",
"NP_BOOLEAN_RETURN_NULL",
"RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN",
+ "OS_OPEN_STREAM",
"REFLC_REFLECTION_MAY_INCREASE_ACCESSIBILITY_OF_CLASS",
"REC_CATCH_EXCEPTION",
"RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
@@ -865,6 +867,8 @@ def _is_exempt(f: Finding) -> bool:
return True
if f.rule == "NN_NAKED_NOTIFY" and "Display.java" in loc:
return True
+ if f.rule == "ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT" and "Deflate.java" in loc:
+ return True
return False
diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java
index b329e3adca..0fcad66206 100644
--- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java
+++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java
@@ -3966,10 +3966,7 @@ public Rectangle getDisplaySafeArea(Rectangle rect) {
* common constants in this class or be a user/implementation defined sound
*/
public void playBuiltinSound(String soundIdentifier) {
- boolean played = playUserSound(soundIdentifier);
- if (!played) {
- return;
- }
+ playUserSound(soundIdentifier);
}
/**
@@ -3977,11 +3974,11 @@ public void playBuiltinSound(String soundIdentifier) {
*
* @param soundIdentifier the sound identifier which can match one of the
* common constants in this class or be a user/implementation defined sound
- * @return true if a user sound exists and was sent to playback
*/
- protected boolean playUserSound(String soundIdentifier) {
- Object sound = builtinSounds.get(soundIdentifier);
- return sound != null;
+ protected void playUserSound(String soundIdentifier) {
+ // TODO: Reintroduce builitin sound support
+ //Object sound = builtinSounds.get(soundIdentifier);
+ //return sound != null;
//playAudio(sound);
}
diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneThread.java b/CodenameOne/src/com/codename1/impl/CodenameOneThread.java
index 66dd820798..021ed7a562 100644
--- a/CodenameOne/src/com/codename1/impl/CodenameOneThread.java
+++ b/CodenameOne/src/com/codename1/impl/CodenameOneThread.java
@@ -23,6 +23,7 @@
package com.codename1.impl;
import com.codename1.io.Log;
+import com.codename1.io.Util;
import com.codename1.ui.Display;
import java.io.DataInputStream;
@@ -133,6 +134,8 @@ public void storeStackForException(Throwable t, int currentStackFrame) {
* Prints the stack trace matching the given stack
*/
public String getStack(Throwable t) {
+ InputStream inp = null;
+ DataInputStream di = null;
try {
StringBuilder b = new StringBuilder();
int size;
@@ -145,11 +148,11 @@ public String getStack(Throwable t) {
}
String[] stk = new String[size];
- InputStream inp = Display.getInstance().getResourceAsStream(getClass(), "/methodData.dat");
+ inp = Display.getInstance().getResourceAsStream(getClass(), "/methodData.dat");
if (inp == null) {
return t.toString();
}
- DataInputStream di = new DataInputStream(inp);
+ di = new DataInputStream(inp);
int totalAmount = di.readInt();
String lastClass = "";
for (int x = 0; x < totalAmount; x++) {
@@ -172,6 +175,9 @@ public String getStack(Throwable t) {
return b.toString();
} catch (IOException ex) {
ex.printStackTrace();
+ } finally {
+ Util.cleanup(di);
+ Util.cleanup(inp);
}
return "Failed in stack generation for " + t;
}
diff --git a/CodenameOne/src/com/codename1/testing/DeviceRunner.java b/CodenameOne/src/com/codename1/testing/DeviceRunner.java
index 04c5405b7a..503e47336f 100644
--- a/CodenameOne/src/com/codename1/testing/DeviceRunner.java
+++ b/CodenameOne/src/com/codename1/testing/DeviceRunner.java
@@ -23,6 +23,7 @@
package com.codename1.testing;
import com.codename1.io.Log;
+import com.codename1.io.Util;
import com.codename1.ui.CN;
import com.codename1.ui.Display;
@@ -48,8 +49,10 @@ public void runTests() {
failedTests = 0;
passedTests = 0;
Log.p("-----STARTING TESTS-----");
+ InputStream is = null;
+ DataInputStream di = null;
try {
- InputStream is = DeviceRunner.class.getResourceAsStream("/tests.dat");
+ is = DeviceRunner.class.getResourceAsStream("/tests.dat");
if (is == null) {
is = Display.getInstance().getResourceAsStream(null, "/tests.dat");
@@ -60,7 +63,7 @@ public void runTests() {
System.exit(2);
return;
}
- DataInputStream di = new DataInputStream(is);
+ di = new DataInputStream(is);
int version = di.readInt();
if (version > VERSION) {
Log.p("Tests were built with a new version of Codename One and can't be executed with this runner");
@@ -72,13 +75,16 @@ public void runTests() {
for (int iter = 0; iter < tests.length; iter++) {
tests[iter] = di.readUTF();
}
- di.close();
+ Util.cleanup(di);
- for (int iter = 0; iter < tests.length; iter++) {
- runTest(tests[iter]);
+ for (String test : tests) {
+ runTest(test);
}
} catch (IOException err) {
TestReporting.getInstance().logException(err);
+ } finally {
+ Util.cleanup(is);
+ Util.cleanup(di);
}
TestReporting.getInstance().testExecutionFinished(getClass().getName());
if (failedTests > 0) {
diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml
index 221cdb8d49..7626676ffb 100644
--- a/maven/core-unittests/spotbugs-exclude.xml
+++ b/maven/core-unittests/spotbugs-exclude.xml
@@ -151,6 +151,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+