Any extensible class might have subclasses located in a different package. When that happens, the use of \`this.getClass().getResource with a relative path would mean that the resource isn’t found for the child class.
Instead, use an absolute path or make the class final\`.
Method or constructor references are more readable than lambda expressions in many situations, and may therefore be preferred.
However, method references are sometimes less concise than lambdas. In such cases, it might be preferrable to keep the lambda expression for better readability. Therefore, this rule only raises issues on lambda expressions where the replacement method reference is shorter.
This rule is automatically disabled when the project’s sonar.java.source is lower than 8, as lambda expressions were introduced in Java 8.
The semantics of Thread and Runnable are different, and while it is technically correct to use Thread where a Runnable is expected, it is a bad practice to do so.
The crux of the issue is that Thread is a larger concept than Runnable. A Runnable represents a task. A Thread represents a task and its execution management (ie: how it should behave when started, stopped, resumed, …). It is both a task and a lifecycle management.
There are two types of stream operations: intermediate operations, which return another stream, and terminal operations, which return something other than a stream. Intermediate operations are lazy, meaning they aren’t actually executed until and unless a terminal stream operation is performed on their results. Consequently, if the result of an intermediate stream operation is not fed to a terminal operation, it serves no purpose, which is almost certainly an error.
When directly subclassing \`java.io.InputStream or java.io.FilterInputStream, the only requirement is that you implement the method read(). However most uses for such streams don’t read a single byte at a time and the default implementation for read(byte\[],int,int) will call read(int) for every single byte in the array which can create a lot of overhead and is utterly inefficient. It is therefore strongly recommended that subclasses provide an efficient implementation of read(byte\[],int,int).
This rule raises an issue when a direct subclass of java.io.InputStream or java.io.FilterInputStream doesn’t provide an override of read(byte\[],int,int)\`.
It’s slightly more efficient to append single characters to StringBuffer and StringBuilder instances as chars, than as Strings. That is, it’s more efficient to put a single char in single quotes, rather than double quotes.
Early classes of the Java API, such as Vector, Hashtable and StringBuffer, were synchronized to make them thread-safe. However, synchronization has a significant negative impact on performance, even when using these collections from a single thread.
It is often best to use their non-synchronized counterparts:
ArrayList or LinkedList instead of Vector
Deque instead of Stack
HashMap instead of Hashtable
StringBuilder instead of StringBuffer
Even when used in synchronized contexts, you should think twice before using their synchronized counterparts, since their usage can be costly. If you are confident the usage is legitimate, you can safely ignore this warning.
When java.io.File#delete fails, this boolean method simply returns false with no indication of the cause. On the other hand, when java.nio.file.Files#delete fails, this void method returns one of a series of exception types to better indicate the cause of the failure. And since more information is generally better in a debugging situation, java.nio.file.Files#delete is the preferred option.
Describing, setting error message or adding a comparator in AssertJ must be done before calling the assertion, otherwise, settings will not be taken into account.
This rule raises an issue when one of the method (with all similar methods):
\`as
describedAs
withFailMessage
overridingErrorMessage
usingComparator
usingElementComparator
extracting
filteredOn\`
is called without calling an AssertJ assertion afterward.
There is potential for confusion if an octal or hexadecimal escape sequence is immediately followed by other characters. Instead, such sequences should be terminated by either:
The start of another escape sequence.
The end of the string.
Placing the array designators \[] after the type helps maintain backward compatibility with older versions of the Java SE platform. This syntax contributes to better readability as it becomes easier to distinguish between array types and non-array types. It helps convey the intention of the method to both the developer implementing it and the developer using it.
Clear and communicative error messages help people understand what went wrong and how to correct the problem. However, care must be taken with \`Servlet error messages because they could expose sensitive information to an attacker. Even sending the user’s own data back to him in an error message could be risky; you never know who might catch a glimpse of the screen.
This rule checks that the strings used in servlet responses made from catch blocks don’t change from call to call. Ideally, such strings would be private static final\`, but that is not enforced by this rule. Logging messages are ignored by this rule.
Regular expressions are powerful but tricky, and even those long used to using them can make mistakes.
The following should not be used as regular expressions:
\`. - matches any single character. Used in replaceAll, it matches everything
| - normally used as an option delimiter. Used stand-alone, it matches the space between characters
File.separator\` - matches the platform-specific file path delimiter. On Windows, this will be taken as an escape character
Spring \`@Controller, @Service, and @Repository classes are singletons by default, meaning only one instance of the class is ever instantiated in the application. Typically such a class might have a few static members, such as a logger, but all non-static members should be managed by Spring and supplied via constructor injection rather than by field injection.
This rule raise an issue when any non-static\` member of a Spring component has an injection annotation.
\`Object.finalize() is called by the Garbage Collector at some point after the object becomes unreferenced.
In general, overloading Object.finalize() is a bad idea because:
The overload may not be called by the Garbage Collector.
Users are not expected to call Object.finalize() and will get confused.
But beyond that it’s a terrible idea to name a method "finalize" if it doesn’t actually override Object.finalize()\`.
The ThreadGroup class contains many deprecated methods like allowThreadSuspension, resume, stop, and suspend. Also, some of the non-deprecated methods are obsolete or not thread-safe, and still others are insecure (activeCount, enumerate). For these reasons, any use of ThreadGroup is suspicious and should be avoided.
The default implementation of java.lang.Thread 's run will only perform a task passed as a Runnable. If no Runnable has been provided at construction time, then the thread will not perform any action.
When extending java.lang.Thread, you should override the run method or pass a Runnable target to the constructor of java.lang.Thread.
Perhaps counter-intuitively, a compareTo method is expected to throw a NullPointerException if passed a null argument, and a ClassCastException if the argument is of the wrong type. So there’s no need to null-test or type-test the argument.
Looking for a given substring starting from a specified offset can be achieved by such code: \`str.substring(beginIndex).indexOf(char1). This works well, but it creates a new String for each call to the substring method. When this is done in a loop, a lot of Strings are created for nothing, which can lead to performance problems if str is large.
To avoid performance problems, String.substring(beginIndex) should not be chained with the following methods:
indexOf(int ch)
indexOf(String str)
lastIndexOf(int ch)
lastIndexOf(String str)
startsWith(String prefix)
For each of these methods, another method with an additional parameter is available to specify an offset.
Using these methods will avoid the creation of additional String\` instances. For indexOf methods, adjust the returned value by subtracting the substring index parameter to obtain the same result.
Stream operations are divided into intermediate and terminal operations, and are combined to form stream pipelines. After the terminal operation is performed, the stream pipeline is considered consumed, and cannot be used again. Such a reuse will yield unexpected results.
Adding messages to JUnit, FEST and AssertJ assertions is an investment in your future productivity. Spend a few seconds writing them now, and you’ll save a lot of time on the other end when either the tests fail and you need to quickly diagnose the problem, or when you need to maintain the tests and the assertion messages work as a sort of documentation.
\`@ComponentScan is used to find which Spring @Component beans (@Service or @Repository or Controller) are available in the classpath so they can be used in the application context. This is a convenient feature especially when you begin a new project but it comes with the drawback of slowing down the application start-up time especially when the application becomes bigger (ie: it references a large JAR file, or it references a significant number of JAR files, or the base-package refers to a large amount of .class files).
@ComponentScan should be replaced by an explicit list of Spring beans loaded by @Import.
The interface @SpringBootApplication is also considered by this rule because it is annotated with @ComponentScan\`.
When you need to perform a complicated initialization of a static member, it should be done in a static initializer block. That’s because such blocks are only executed when the class is loaded into the JVM. That is, they run only once, and that happens before any instances are created. Non-static blocks, on the other hand, run once for each instance that’s created, so any static members "initialized" in such a block will be re-set for each new instance.
In Java 15 Text Blocks are now official and can be used. The most common pattern for multiline strings in Java \< 15 was to write String concatenation. Now it’s possible to do it in a more natural way using Text Blocks.
When testing exception via org.junit.rules.ExpectedException any code after the raised exception will not be executed, so adding subsequent assertions is wrong and misleading. This rule raises an issue when an assertion is done after the "expect(…)" invocation, only the code throwing the expected exception should be after "expect(…)".
You should consider using org.junit.Assert.assertThrows instead, it’s available since JUnit 4.13 and it allows additional subsequent assertions.
Alternatively, you could use try-catch idiom for JUnit version \< 4.13 or if your project does not support lambdas.
Spring provides two options to mark a REST parameter as optional:
Use required = false in the @PathVariable or @RequestParam annotation of the respective method parameter or
Use type java.util.Optional\
When using 1., the absence of the parameter, when the REST function is called, is encoded by null, which can only be used for object types. If required = false is used for a parameter with a primitive and the REST function is called without the parameter, a runtime exception occurs because the Spring data mapper cannot map the null value to the parameter.
Assertion methods are throwing a "`java.lang.AssertionError`". If this call is done within the try block of a try-catch cathing a similar error, you should make sure to test some properties of the exception. Otherwise, the assertion will never fail.
If the credentials provider is not specified when creating a new AwsClient with an AwsClientBuilder, the AWS SDK will execute some logic to identify it automatically.
While it will probably identify the correct one, this extra logic will slow down startup time, already known to be a hotspot.
You should therefore always define the logic to set the credentials provider yourself. This is typically done by retrieving it from the Lambda provided environment variable.
This will make the code more explicit and spare initialization time.
This rule reports an issue when the credentials provider is not set when creating an AwsClient.
Standard applications don’t require a display refresh rate above 60Hz, hence it is advisable to avoid higher frequencies to avoid unnecessary energy consumption.
The rule flags an issue when setFrameRate() is invoked with a frameRate higher than 60Hz for android.view\.Surface and android.view\.SurfaceControl.Transaction.
It’s important to note that the scheduler considers several factors when determining the display refresh rate. Therefore, using setFrameRate() doesn’t guarantee your app will achieve the requested frame rate.
Once set, the value of a Hibernate @Entity's @Id field/column should never be updated. Therefore, setters for such fields should always be private.
According to the API documentation of the HttpServletRequest.getRequestedSessionId() method:
Returns the session ID specified by the client. This may not be the same as the ID of the current valid session for this request. If the client did not specify a session ID, this method returns null.
The session ID it returns is either transmitted through a cookie or a URL parameter. This allows an end user to manually update the value of this session ID in an HTTP request.
Due to the ability of the end-user to manually change the value, the session ID in the request should only be used by a servlet container (e.g. Tomcat or Jetty) to see if the value matches the ID of an existing session. If it does not, the user should be considered unauthenticated.
The use of a "RESOURCE\_LOCAL" persistence-unit makes you responsible for your own entity management, which involves a lot of extra boilerplate code to get right. Instead, set this to "JPA" in a JavaSE environment or omit it altogether in a JavaEE environment, where "JPA" is the default.
The PreparedStatement is frequently used in loops because it allows to conveniently set parameters. A small optimization is possible by setting constant parameters outside the loop or hard-coding them in the query whenever possible.
Operations performed on a string with predictable outcomes should be avoided. For example:
checking if a string contains itself
comparing a string with itself
matching a string against itself
creating a substring from 0 to the end of the string
creating a substring from the end of the string
replacing a string with itself
replacing a substring with the exact substring
The fields in an HTTP request are putty in the hands of an attacker, and you cannot rely on them to tell you the truth about anything. While it may be safe to store such values after they have been neutralized, decisions should never be made based on their contents.
This rule flags uses of the referer header field.
In java 7 to 9, FileInputStream and FileOutputStream rely on finalization to perform final closes if the stream is not already closed. Whether or not the stream is already closed, the finalizer will be called, resulting in extra work for the garbage collector. This can easily be avoided using the Files API.
Two classes can have the same simple name if they are in two different packages.
The Comparable.compareTo method returns a negative integer, zero, or a positive integer to indicate whether the object is less than, equal to, or greater than the parameter. The sign of the return value or whether it is zero is what matters, not its magnitude.
Returning a positive or negative constant value other than the basic ones (-1, 0, or 1) provides no additional information to the caller. Moreover, it could potentially confuse code readers who are trying to understand its purpose.
There is no good reason to declare a field "public" and "static" without also declaring it "final". Most of the time this is a kludge to share a state among several objects. But with this approach, any object can do whatever it wants with the shared state, such as setting it to null.
A try-catch block is used to handle exceptions or errors that may occur during the execution of a block of code. It allows you to catch and handle exceptions gracefully, preventing your program from terminating abruptly.
The code that may throw an exception is enclosed within the try block, while each catch block specifies the type of exception it can handle. The corresponding catch block is executed if the exception matches the type specified in any catch block. It is unnecessary to manually check the types using instanceof because Java automatically matches the exception type to the appropriate catch block based on the declared exception type in the catch clauses.
For optimal code readability, annotation arguments should be specified in the same order that they were declared in the annotation definition.
Assertions comparing incompatible types always fail, and negative assertions always pass. At best, negative assertions are useless. At worst, the developer loses time trying to fix his code logic before noticing wrong assertions.
Dissimilar types are:
comparing a primitive with null
comparing an object with an unrelated primitive (E.G. a string with an int)
comparing unrelated classes
comparing an array to a non-array
comparing two arrays of dissimilar types
This rule also raises issues for unrelated class and interface or unrelated interface types in negative assertions. Because except in some corner cases, those types are more likely to be dissimilar. And inside a negative assertion, there is no test failure to inform the developer about this unusual comparison.
Supported test frameworks:
JUnit4
JUnit5
AssertJ
The location awareness feature can significantly drain the device’s battery.
The recommended way to maximize the battery life is to use the fused location provider which combines signals from GPS, Wi-Fi, and cell networks, as well as accelerometer, gyroscope, magnetometer and other sensors. The FusedLocationProviderClient automatically chooses the best method to retrieve a device’s location based on the device’s context.
The rule flags an issue when android.location.LocationManager or com.google.android.gms.location.LocationClient is used instead of com.google.android.gms.location.FusedLocationProviderClient.
Creating temporary primitive wrapper objects only for String conversion or the use of the compareTo() method is inefficient.
Instead, the static toString() or compare() method of the primitive wrapper class should be used.
Referencing a static member of a subclass from its parent during class initialization, makes the code more fragile and prone to future bugs. The execution of the program will rely heavily on the order of initialization of classes and their static members.
An indexOf or lastIndexOf call with a single letter String can be made more performant by switching to a call with a char argument.
This rule allows you to track the use of the PMD suppression comment mechanism.
s keys will be valid until you manually revoke them. This makes them highly sensitive as any exposure can have serious consequences and should be used with care.
This rule will trigger when encountering an instantiation of com.amazonaws.auth.BasicAWSCredentials.
Using boxed type suggests that null is a possible value for the variable. Use of the primitive type should be preferred if this is not the case to avoid any confusion about possible values variable can contain.
Appending String.valueOf() to a String decreases the code readability.
The argument passed to String.valueOf() should be directly appended instead.
Programming languages evolve over time, and new versions of Java introduce additional keywords. If future keywords are used in the current code, it can create compatibility issues when transitioning to newer versions of Java. The code may fail to compile or behave unexpectedly due to conflicts with newly introduced keywords.
The following keywords are marked as invalid identifiers:
| Keyword | Added in version |
|---|---|
\_ |
9 |
enum |
5.0 |
assert and strictfp are another example of valid identifiers which became keywords in later versions, but are not supported by this rule.
Boxing is the process of putting a primitive value into a wrapper object, such as creating an Integer to hold an int value. Unboxing is the process of retrieving the primitive value from such an object. Since the original value is unchanged during boxing and unboxing, there is no point in doing either when not needed.
Instead, you should rely on Java’s implicit boxing/unboxing to convert from the primitive type to the wrapper type and vice versa, for better readability.
As stated per effective java :
Varargs methods are a convenient way to define methods that require a variable number of arguments, but they should not be overused. They can produce confusing results if used inappropriately.
According to the Java Language Specification, there is a contract between \`equals(Object) and hashCode():
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode\` method on each of the two objects must produce distinct integer results.
However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
In order to comply with this contract, those methods should be either both inherited, or both overridden.
Each constructor must first invoke a parent class constructor, but it doesn’t always have to be done explicitly. If the parent class has a reachable, no-args constructor, a call to it will be inserted automatically by the compiler. Thus, calls to super() can be omitted.
The \`setUp() and tearDown() methods (initially introduced with JUnit3 to execute a block of code before and after each test) need to be correctly annotated with the equivalent annotation in order to preserve the same behavior when migrating from JUnit3 to JUnit4 or JUnit5.
This rule consequently raise issues on setUp() and tearDown()\` methods which are not annotated in test classes.
A cleanly coded web application will have a clear separation of concerns, with business logic in the \`@Service layer, and communication with other systems in the data access layer.
To help enforce such a separation of concerns, this rule raises an issue when a @Service class has RestTemplate, JmsTemplate, WebServiceTemplate, JdbcTemplate, or DataSource\` member.
The equals and hashCode methods of java.net.URL may trigger a name service lookup (typically DNS) to resolve the hostname or IP address. Depending on the configuration, and network status, this lookup can be time-consuming.
On the other hand, the URI class does not perform such lookups and is a better choice unless you specifically require the functionality provided by URL.
In general, it is better to use the URI class until access to the resource is actually needed, at which point you can convert the URI to a URL using URI.toURL().
This rule checks for uses of URL 's in Map and Set , and for explicit calls to the equals and hashCode methods. It suggests reconsidering the use of URL in such scenarios to avoid potential performance issues related to name service lookups.
It is preferable to place string literals on the left-hand side of an equals() or equalsIgnoreCase() method call.
This prevents null pointer exceptions from being raised, as a string literal can never be null by definition.
It is convention to name each class’s logger for the class itself. Doing so allows you to set up clear, communicative logger configuration. Naming loggers by some other convention confuses configuration, and using the same class name for multiple class loggers prevents the granular configuration of each class' logger. Some libraries, such as SLF4J warn about this, but not all do.
This rule raises an issue when a logger is not named for its enclosing class.
If an InterruptedException or a ThreadDeath error is not handled properly, the information that the thread was interrupted will be lost. Handling this exception means either to re-throw it or manually re-interrupt the current thread by calling Thread.interrupt(). Simply logging the exception is not sufficient and counts as ignoring it. Between the moment the exception is caught and handled, is the right time to perform cleanup operations on the method’s state, if needed.
Using a \`type="timestamp" column as the primary key of a table is slightly risky. Two threads could create new objects in the table close enough in sequence for them to both have the same timestamp. Alternately, this could happen during a daylight savings time change. Instead, use a numeric value as the @Id.
This rule raises an issue when a time or date-related class is annotated with @Id\`.
The class \`java.util.zip.GZIPInputStream is already buffering its input while reading. Thus passing a java.io.BufferedInputStream to a java.util.zip.GZIPInputStream is redundant. It is more efficient to directly pass the original input stream to java.util.zip.GZIPInputStream.
Note that the default buffer size of GZIPInputStream is not the same as the one in BufferedInputStream. Configure it if need be.
This rule raises an issue when a java.util.zip.GZIPInputStream reads from a java.io.BufferedInputStream\`.
The JDK provides a set of built-in methods to copy the contents of an array into another array. Using a loop to perform the same operation is less clear, more verbose and should be avoided.
There are several reasons to avoid using this method:
It is optionally available only for result sets of type ResultSet.TYPE\_FORWARD\_ONLY. Database drivers will throw an exception if not supported.
The method can be expensive to execute as the database driver may need to fetch ahead one row to determine whether the current row is the last in the result set. The documentation of the method explicitly mentions this fact.
What "the cursor is on the last row" means for an empty ResultSet is unclear. Database drivers may return true or false in this case .
ResultSet.next() is a good alternative to ResultSet.isLast() as it does not have the mentioned issues. It is always supported and, as per specification, returns false for empty result sets.
A return type containing wildcards cannot be narrowed down in any context. This indicates that the developer’s intention was likely something else.
The core problem lies in type variance. Expressions at an input position, such as arguments passed to a method, can have a more specific type than the type expected by the method, which is called covariance. Expressions at an output position, such as a variable that receives the return result from a method, can have a more general type than the method’s return type, which is called contravariance. This can be traced back to the Liskov substitution principle.
In Java, type parameters of a generic type are invariant by default due to their potential occurrence in both input and output positions at the same time. A classic example of this is the methods T get() (output position) and add(T element) (input position) in interface java.util.List. We could construct cases with invalid typing in List if T were not invariant.
Wildcards can be employed to achieve covariance or contravariance in situations where the type parameter appears in one position only:
\ extends Foo> for covariance (input positions)
\ super Foo> for contravariance (output positions)
However, covariance is ineffective for the return type of a method since it is not an input position. Making it contravariant also has no effect since it is the receiver of the return value which must be contravariant (use-site variance in Java). Consequently, a return type containing wildcards is generally a mistake.
It’s almost always a mistake to compare two instances of java.lang.String or boxed types like java.lang.Integer using reference equality == or !=, because it is not comparing actual value but locations in memory.
When verifying that code raises an exception, a good practice is to avoid having multiple method calls inside the tested code, to be explicit about what is exactly tested.
When two of the methods can raise the same checked exception, not respecting this good practice is a bug, since it is not possible to know what is really tested.
You should make sure that only one method can raise the expected checked exception in the tested code.
Map is an object that maps keys to values. A map cannot contain duplicate keys, which means each key can map to at most one value.
When both the key and the value are needed, it is more efficient to iterate the entrySet(), which will give access to both instead of iterating over the keySet() and then getting the value.
If the entrySet() method is not iterated when both the key and value are needed, it can lead to unnecessary lookups. This is because each lookup requires two operations: one to retrieve the key and another to retrieve the value. By iterating the entrySet() method, the key-value pair can be retrieved in a single operation, which can improve performance.
The use of exact alarms triggers the device to wake up at precise times that can lead several wake-ups in a short period of time. The wake-up mechanism is a significant battery drain because it requires powering up the main processor and pulling it out of a low-power state.
It’s highly recommended to create an inexact alarm whenever possible.
It is also recommended for normal timing operations, such as ticks and timeouts, using the Handler, and for long-running operations, such as network downloads, using WorkManager or JobScheduler.
\`Bean Validation as per defined by JSR 380 can be triggered programmatically or also executed by the Bean Validation providers. However something should tell the Bean Validation provider that a variable must be validated otherwise no validation will happen. This can be achieved by annotating a variable with javax.validation.Valid and unfortunally it’s easy to forget to add this annotation on complex Beans.
Not annotating a variable with @Valid means Bean Validation will not be triggered for this variable, but readers may overlook this omission and assume the variable will be validated.
This rule will run by default on all Class'es and therefore can generate a lot of noise. This rule should be restricted to run only on certain layers. For this reason, the "Restrict Scope of Coding Rules" feature should be used to check for missing @Valid\` annotations only on some packages of the application.
Using FetchType.EAGER can lead to inefficient data loading and potential performance issues. Eager Loading initializes associated data on the spot, potentially fetching more data than needed.
Synchronizing on a class field synchronizes not on the field itself, but on the object assigned to it. So synchronizing on a non-final field makes it possible for the field’s value to change while a thread is in a block synchronized on the old value. That would allow a second thread, synchronized on the new value, to enter the block at the same time.
The story is very similar for synchronizing on parameters; two different threads running the method in parallel could pass two different object instances in to the method as parameters, completely undermining the synchronization.
According to the JDBC specification:
Blob, Clob, and NClobJava objects remain valid for at least the duration of the transaction in which they are created. This could potentially result in an application running out of resources during a long running transaction.
Without OAEP in RSA encryption, it takes less work for an attacker to decrypt the data or infer patterns from the ciphertext. This rule logs an issue as soon as a literal value starts with RSA/NONE.
Java 21 introduces a new SequencedCollection interface that provides a uniform API for accessing its first and last elements. The new getFirst() and getLast() methods offer a consistent way to access elements across SortedSet, NavigableSet, LinkedHashSet, List and Deque collections. Because those methods are more concise and readable, they should be used instead of more complex workarounds that recreate the same behavior.
For example, list.get(list.size() - 1) can be replaced by list.getLast().
This rule identifies code that can be simplified by using the new getFirst() and getLast() methods.
Proper synchronization and thread management can be tricky under the best of circumstances, but it’s particularly difficult in JEE application, and is even forbidden under some circumstances by the JEE standard.
This rule raises an issue for each Runnable, and use of the synchronized keyword.
NullPointerException should be avoided, not caught. Any situation in which NullPointerException is explicitly caught can easily be converted to a null test, and any behavior being carried out in the catch block can easily be moved to the "is null" branch of the conditional.
Testing equality of an enum value with \`equals is perfectly valid because an enum is an Object and every Java developer knows "==" should not be used to compare the content of an Object. At the same time, using "==" on enums:
provides the same expected comparison (content) as equals
is more null-safe than equals()
provides compile-time (static) checking rather than runtime checking
For these reasons, use of "==" should be preferred to equals\`.
The difference between \`private and protected visibility is that child classes can see and use protected members, but they cannot see private ones. Since a final class will have no children, marking the members of a final class protected is confusingly pointless.
Note that the protected\` members of a class can also be seen and used by other classes that are placed within the same package, this could lead to accidental, unintended access to otherwise private members.
Shared coding conventions allow teams to collaborate effectively. While types for lambda arguments are optional, specifying them anyway makes the code clearer and easier to read.
An ObjectOutputStream writes primitive data types and graphs of Java objects to an OutputStream. The objects can be read (reconstituted) using an ObjectInputStream.
When ObjectOutputStream is used with files opened in append mode, it can cause data corruption and unexpected behavior. This is because when ObjectOutputStream is created, it writes metadata to the output stream, which can conflict with the existing metadata when the file is opened in append mode. This can lead to errors and data loss.
When used with serialization, an ObjectOutputStream first writes the serialization stream header. This header should appear once per file at the beginning. When you’re trying to read your object(s) back from the file, only the first one will be read successfully, and a StreamCorruptedException will be thrown after that.
There is no good reason to have a mutable object as the \`public (by default), static member of an interface. Such variables should be moved into classes and their visibility lowered.
Similarly, mutable static members of classes and enumerations which are accessed directly, rather than through getters and setters, should be protected to the degree possible. That can be done by reducing visibility or making the field final if appropriate.
Note that making a mutable field, such as an array, final will keep the variable from being reassigned, but doing so has no effect on the mutability of the internal state of the array (i.e. it doesn’t accomplish the goal).
This rule raises issues for public static array, Collection, Date, and awt.Point\` members.
The order in which you `close database-releated resources is crucial. Close a Connection first, and depending on the database pooling in use, you may no longer be able to truly reach its Statements and ResultSet`s to close them, even though the calls are made and execute without error.
When an SWT \`Image accesses a file directly, it holds the file handle for the life of the image. Do this many times, and the OS may run out of available file handles. At minimum, SWT Images which directly access files should not be static. At best, they should access their files through ImageDescriptors, which do not hold open file handles.
This rule looks for org.eclipse.swt.graphics.Images which both directly access a file on the file path and are static\`.
ialization of objects from LDAP directories, which can lead to remote code execution.
This rule raises an issue when an LDAP search query is executed with SearchControls configured to allow deserialization.
Transactional methods have a propagation type parameter in the @Transaction annotation that specifies the requirements about the transactional context in which the method can be called and how it creates, appends, or suspends an ongoing transaction.
When an instance that contains transactional methods is injected, Spring uses proxy objects to wrap these methods with the actual transaction code.
However, if a transactional method is called from another method in the same class, the this argument is used as the receiver instance instead of the injected proxy object, which bypasses the wrapper code. This results in specific transitions from one transactional method to another, which are not allowed:
| From | To |
|---|---|
non-\`@Transactional |
MANDATORY, NESTED, REQUIRED, REQUIRES\_NEW |
MANDATORY |
NESTED, NEVER, NOT\_SUPPORTED, REQUIRES\_NEW |
NESTED |
NESTED, NEVER, NOT\_SUPPORTED, REQUIRES\_NEW |
NEVER |
MANDATORY, NESTED, REQUIRED, REQUIRES\_NEW |
NOT\_SUPPORTED |
MANDATORY, NESTED, REQUIRED, REQUIRES\_NEW |
REQUIRED or @Transactional\` |
NESTED, NEVER, NOT\_SUPPORTED, REQUIRES\_NEW |
REQUIRES\_NEW |
NESTED, NEVER, NOT\_SUPPORTED, REQUIRES\_NEW |
SUPPORTS |
MANDATORY, NESTED, NEVER, NOT\_SUPPORTED, REQUIRED, REQUIRES\_NEW |
The equals method in AtomicInteger and AtomicLong returns true only if two instances are identical, not if they represent the same number value.
This is because equals is not part of the API contract of these classes, and they do not override the method inherited from java.lang.Object. Although both classes implement the Number interface, assertions about equals comparing number values are not part of that interface either. Only the API contract of implementing classes like Integer, Long, Float, BigInteger, etc., provides such assertions.
A method with a \`@RequestMapping annotation part of a class annotated with @Controller (directly or indirectly through a meta annotation - @RestController from Spring Boot is a good example) will be called to handle matching web requests. That will happen even if the method is private, because Spring invokes such methods via reflection, without checking visibility.
So marking a sensitive method private may seem like a good way to control how such code is called. Unfortunately, not all Spring frameworks ignore visibility in this way. For instance, if you’ve tried to control web access to your sensitive, private, @RequestMapping method by marking it @Secured … it will still be called, whether or not the user is authorized to access it. That’s because AOP proxies are not applied to private methods.
In addition to @RequestMapping, this rule also considers the annotations introduced in Spring Framework 4.3: @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping\`.
Java 21 enhances Pattern Matching, introduced in Java 16, with a record pattern that decomposes records into local variables. This form should be used when all fields of a record are accessed within a block for improved readability. Nested record patterns are also allowed and should be used when a record field is another record, and all its fields are accessed.
A loop with at most one iteration is equivalent to an if statement. This can confuse developers and make the code less readable since loops are not meant to replace if statements.
If the intention was to conditionally execute the block only once, an if statement should be used instead. Otherwise, the loop should be fixed so the loop block can be executed multiple times.
A loop statement with at most one iteration can happen when a statement that unconditionally transfers control, such as a jump or throw statement, is misplaced inside the loop block.
This rule arises when the following statements are misplaced:
break
return
throw
With Java 8, there’s no need to write \`Comparators that compare primitive values or other Comparables; they can be generated for you using the Comparator.comparing\* functions: comparing, comparingDouble, comparingInt, comparingLong.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8\`.
Monster Classes become monolithic entities, with numerous responsibilities and functionalities packed into a single class. This is problematic because it violates the Single Responsibility Principle, which states that a class should have only one reason to change.
When a class has too many responsibilities and functionalities, it becomes difficult to maintain. Changes to one part of the class can unintentionally affect other parts, leading to bugs. Additionally, it can be difficult to test the class, as there may be many different interactions between different parts of the class that need to be considered.
Needing to cast from an interface to a concrete type indicates that something is wrong with the abstractions in use, likely that something is missing from the interface. Instead of casting to a discrete type, the missing functionality should be added to the interface. Otherwise there is the risk of runtime exceptions.
Optimizing resource usage and preventing unnecessary battery drain are critical considerations in Android development. Failing to release sensor resources when they are no longer needed can lead to prolonged device activity, negatively impacting battery life. Common Android sensors, such as cameras, GPS, and microphones, provide a method to release resources after they are not in use anymore.
This rule identifies situations where a sensor is not released after being utilized, helping developers maintain efficient and battery-friendly applications.
Missing call to release() method:
android.os.PowerManager.WakeLock
android.net.wifi.WifiManager\$MulticastLock
android.hardware.Camera
android.media.MediaPlayer
android.media.MediaRecorder
android.media.SoundPool
android.media.audiofx.Visualizer
android.hardware.display.VirtualDisplay
Missing call to close() method
android.hardware.camera2.CameraDevice
Missing call to removeUpdates() method:
android.location.LocationManager
Missing call to unregisterListener() method:
android.hardware.SensorManager
enums are generally thought of as constant, but an enum with a public field or public setter is non-constant. Ideally fields in an enum are private and set in the constructor, but if that’s not possible, their visibility should be reduced as much as possible.
When all the elements in a Set are values from the same enum, the Set can be replaced with an EnumSet, which can be much more efficient than other sets because the underlying data structure is a simple bitmap.
Returning null when something goes wrong instead of throwing an exception leaves callers with no understanding of what went wrong. Instead, an exception should be thrown.
The JEE standard forbids the direct management of connections in JEE applications. The application code should not directly create, manage, or close database connections. Instead, the application code should use the connection pool managed by the container via DataSource objects.
The container is responsible for creating and managing the connection pool, as well as monitoring the usage of connections and releasing them when they are no longer needed. By delegating connection management to the container, JEE applications can avoid connection leaks and resource exhaustion and ensure that database connections are used efficiently and securely.
When an application manages connections directly, connection leaks may arise. These leaks occur when an application fails to release a database connection after it has finished using it. Another risk is vulnerability to SQL injection attacks, which occur when an attacker is able to inject malicious SQL code into an application’s database queries, allowing them to access or modify sensitive data. Finally, these applications have difficulty managing and monitoring database connections. Without a centralized connection pool, tracking the usage of database connections and ensuring they are used efficiently and securely can be challenging.
This rule raises an issue for using a DriverManager in a servlet class.
\`sealed classes were introduced in Java 17. This feature is very useful if there is a need to define a strict hierarchy and restrict the possibility of extending classes. In order to mention all the allowed subclasses, there is a keyword permits, which should be followed by subclasses' names.
This notation is quite useful if subclasses of a given sealed class can be found in different files, packages, or even modules. In case when all subclasses are declared in the same file there is no need to mention the explicitly and permits part of a declaration can be omitted.
This rule reports an issue if all subclasses of a sealed\` class are declared in the same file as their superclass.
Mockito provides argument matchers for flexibly stubbing or verifying method calls.
\`Mockito.verify(), Mockito.when(), Stubber.when() and BDDMockito.given() each have overloads with and without argument matchers.
However, the default matching behavior (i.e. without argument matchers) uses equals(). If only the matcher org.mockito.ArgumentMatchers.eq() is used, the call is equivalent to the call without matchers, i.e. the eq()\` is not necessary and can be omitted. The resulting code is shorter and easier to read.
Marking a non-public method @Async or @Transactional is misleading because Spring does not recognize non-public methods, and so makes no provision for their proper invocation. Nor does Spring make provision for the methods invoked by the method it called.
Therefore marking a private method, for instance, @Transactional can only result in a runtime error or exception if the method is annotated as @Transactional.
Under the reasoning that cleaner code is better code, the semicolon at the end of a try-with-resources construct should be omitted because it can be omitted.
The java.util.concurrent.locks.Condition interface provides an alternative to the Object monitor methods (wait, notify and notifyAll). Hence, the purpose of implementing said interface is to gain access to its more nuanced await methods.
Consequently, calling the method Object.wait on a class implementing the Condition interface is contradictory and should be avoided. Use Condition.await instead.
The Java Language Specification recommends listing modifiers in the following order:
Annotations
public
protected
private
abstract
static
final
transient
volatile
synchronized
native
default
strictfp
Not following this convention has no technical impact, but will reduce the code’s readability because most developers are used to the standard order.
Assembling a StringBuilder or StringBuffer into a String merely to see if it’s empty is a waste of cycles. Instead, jump right to the heart of the matter and get its .length() instead.
An exception in a \`throws declaration in Java is superfluous if it is:
listed multiple times
a subclass of another listed exception
a RuntimeException\`, or one of its descendants
completely unnecessary because the declared exception type cannot actually be thrown
When a developer uses the StringBuilder or StringBuffer constructor with a single character as an argument, the likely intention is to create an instance with the character as the initial string value.
However, this is not what happens because of the absence of a dedicated StringBuilder(char) or StringBuffer(char) constructor. Instead, StringBuilder(int) or StringBuffer(int) is invoked, which results in an instance with the provided int value as the initial capacity of the StringBuilder or StringBuffer.
The reason behind this behavior lies in the automatic widening of char expressions to int when required. Consequently, the UTF-16 code point value of the character (for example, 65 for the character 'A') is interpreted as an int to specify the initial capacity.
The @PathVariable annotation in Spring extracts values from the URI path and binds them to method parameters in a Spring MVC controller. It is commonly used with @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping to capture path variables from the URI. These annotations map HTTP requests to specific handler methods in a controller. They are part of the Spring Web module and are commonly used to define the routes for different HTTP operations in a RESTful API.
If a method has a path template containing a placeholder, like "/api/resource/\{id}", and there’s no @PathVariable annotation on a method parameter to capture the id path variable, Spring will disregard the id variable.
When creating an instance of HashMap or HashSet, the developer can pick a constructor with known capacity. However, the requested capacity is not fully allocated by default. Indeed, when the collection reaches the load factor of the collection (default: 0.75), the collection is resized on the fly, leading to unexpected performance issues.
Sometimes when implementing a method, there is a need to return more than one value. To reduce the boilerplate of describing another class, other programming languages introduced such structures as \`Pair, Tuple, Vector, etc.
Unfortunately, in Java, there is no such structure and ++Map.Entry++ or ++Object\[]++ of fixed size are used as a workaround for returning multiple values from a method.
Java 16 introduced records to represent immutable data structures and they can be used for grouping different values in one entity. By using records, developers will have meaningful names and result in a more readable code. Furthermore, when using Object\[], there is a risk of getting ClassCastException or ArrayIndexOutOfBoundsException if not used carefully. It means that using records is not only more readable but is definitely safer.
This rule should report an issue when Object\[] of a fixed size (\< 7) or Map.Entry\` are returned from a private method.
The Object.clone / java.lang.Cloneable mechanism in Java should be considered broken for the following reasons and should, consequently, not be used:
Cloneable is a marker interface without API but with a contract about class behavior that the compiler cannot enforce. This is a bad practice.
Classes are instantiated without calling their constructor, so possible preconditions cannot be enforced.
There are implementation flaws by design when overriding Object.clone, like type casts or the handling of CloneNotSupportedException exceptions.
\`PreparedStatements and CallableStatements (for stored procedures) are safer and more efficient than Statements and should always be preferred.
This rule raises an issue each time a Statement\` is declared.
The Java Collections API offers a well-structured hierarchy of interfaces designed to hide collection implementation details. For the various collection data structures like lists, sets, and maps, specific interfaces (java.util.List, java.util.Set, java.util.Map) cover the essential features.
When passing collections as method parameters, return values, or when exposing fields, it is generally recommended to use these interfaces instead of the implementing classes. The implementing classes, such as java.util.LinkedList, java.util.ArrayList, and java.util.HasMap, should only be used for collection instantiation. They provide finer control over the performance characteristics of those structures, and developers choose them depending on their use case.
For example, if fast random element access is essential, java.util.ArrayList should be instantiated. If inserting elements at a random position into a list is crucial, a java.util.LinkedList should be preferred. However, this is an implementation detail your API should not expose.
There are many ways to implement the Singleton pattern in Java, but none of them is as clean, compact and close to fool-proof as using an enum. Without an enum, the implementer must take care to properly handle thread-safety, serialization, and classloaders, but those things come for free with an enum.
According to the EJB specification:
An enterprise bean must not attempt to listen on a socket, accept connections on a socket, or use a socket for multicast.
…
The enterprise bean must not attempt to set the socket factory used by ServerSocket, Socket, or the stream handler factory used by URL.
These networking functions are reserved for the EJB container. Allowing the enterprise bean to use these functions could compromise security and decrease the container’s ability to properly manage the runtime environment.
Since EJB’s may be passivated (temporarily serialized at the discretion of the container), using sockets in an EJB could cause resource leaks. Instead, you should work at a higher level and let the container handle such resources.
This rule raises an issue each time a socket is created or or retrieved from another class in a servlet class or EJB.
This rule raises an issue when required properties are not included in a project’s pom.
Java 21 has introduced enhancements to switch statements and expressions, allowing them to operate on any type, not just specific ones, as in previous versions. Furthermore, case labels have been upgraded to support patterns, providing an alternative to the previous restriction of only accepting constants.
It is equivalent to use the equality \`== operator and the equals method to compare two objects if the equals method inherited from Object has not been overridden. In this case both checks compare the object references.
But as soon as equals is overridden, two objects not having the same reference but having the same value can be equal. This rule spots suspicious uses of == and != operators on objects whose equals\` methods are overridden.
The creation of a JAXBContext.newInstance is a costly operation, and should only be performed once per context and stored - preferably in a static member - for reuse.
In fact, according to the JAXB 2.2 Specification:
To avoid the overhead involved in creating a JAXBContext instance, a JAXB application is encouraged to reuse a JAXBContext instance. An implementation of abstract class JAXBContext is required to be thread-safe, thus, multiple threads in an application can share the same JAXBContext instance.
This rule raises an issue when multiple instances are created for the same context path.
A common good practice is to write test methods targeting only one logical concept, that can only fail for one reason.
While it might make sense to have more than one assertion to test one concept, having too many is a sign that a test became too complex and should be refactored to multiples ones.
This rule will report any test method containing more than a given number of assertion.
A non-static inner class has a reference to its outer class, and access to the outer class' fields and methods. That class reference makes the inner class larger and could cause the outer class instance to live in memory longer than necessary.
If the reference to the outer class isn’t used, it is more efficient to make the inner class \`static (also called nested). If the reference is used only in the class constructor, then explicitly pass a class reference to the constructor. If the inner class is anonymous, it will also be necessary to name it.
However, while a nested/static class would be more efficient, it’s worth noting that there are semantic differences between an inner class and a nested one:
an inner class can only be instantiated within the context of an instance of the outer class.
a nested (static\`) class can be instantiated independently of the outer class.
Cloneable is a marker interface that defines the contract of the Object.clone method, which is to create a consistent copy of the instance. The clone method is not defined by the interface though, but by class Objects.
The general problem with marker interfaces is that their definitions cannot be enforced by the compiler because they have no own API. When a class implements Cloneable but does not override Object.clone, it is highly likely that it violates the contract for Cloneable.
Annotating unit tests with more than one test-related annotation is not only useless but could also result in unexpected behavior like failing tests or unwanted side-effects.
This rule reports an issue when a test method is annotated with more than one of the following competing annotation:
@Test
@RepeatedTest
@ParameterizedTest
@TestFactory
@TestTemplate
Java 8 adds \`Comparator.comparing to allow the creation of a single-value comparator to be shorthanded into a single call. This cleaner syntax should be preferred.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8\`.
Including any logic other than a simple return of the field in a persistence-annotated method can result in odd behavior, including for example, the default construction of empty members which are annotated to be lazy.
Shared naming conventions allow teams to collaborate efficiently. This rule raises an issue when a test method name does not match the provided regular expression.
AssertJ assertions taking \`Consumer objects as arguments are expected to contain "requirements", which should themselves be expressed as assertions. This concerns the following methods: allSatisfy, anySatisfy, hasOnlyOneElementSatisfying, isInstanceOfSatisfying, noneSatisfy, satisfies, satisfiesAnyOf, zipSatisfy.
These methods are assuming the Consumer will do the assertions itself. If you do not do any assertion in the Consumer, it probably means that you are inadvertently only partially testing your object.
This rule raises an issue when a Consumer\` argument of any of the above methods does not contain any assertion.
Serialization is a platform-independent mechanism for writing the state of an object into a byte-stream. For serializing the object, we call the writeObject() method of java.io.ObjectOutputStream class. Only classes that implement Serializable or extend a class that does it can successfully be serialized (or de-serialized).
Attempting to write a class with the writeObject method of the ObjectOutputStream class that does not implement Serializable or extends a class that implements it, will throw an IOException.
Providing a \`serialVersionUID field on Serializable classes is strongly recommended by the Serializable documentation but blindly following that recommendation can be harmful.
serialVersionUID value is stored with the serialized data and this field is verified when deserializing the data to ensure that the code reading the data is compatible with the serialized data. In case of failure, it means the serialized data and the code are not in sync and this fine because you know what’s wrong.
When the serialVersionUID is generated by an IDE or blindly hard-coded, there is a high probability that one will forget to update the serialVersionUID value when the Serializable class is later enriched with additional fields. As a consequence, old serialized data will incorrectly be considered compatible with the newer version of the code creating situations which are hard to debug.
Therefore, defining serialVersionUID should be done with care. This rule raises an issue on each serialVersionUID field declared on classes implementing Serializable to be sure the presence and the value of the serialVersionUID\` field is challenged and validated by the team.
The \`Files.exists method has noticeably poor performance in JDK 8, and can slow an application significantly when used to check files that don’t actually exist.
The same goes for Files.notExists, Files.isDirectory and Files.isRegularFile from java.nio.file package.
Note that this rule is automatically disabled when the project’s sonar.java.source\` is not 8.
Catching \`Exception seems like an efficient way to handle multiple possible exceptions. Unfortunately, it traps all exception types, both checked and runtime exceptions, thereby casting too broad a net. Indeed, was it really the intention of developers to also catch runtime exceptions? To prevent any misunderstanding, if both checked and runtime exceptions are really expected to be caught, they should be explicitly listed in the catch clause.
This rule raises an issue if Exception is caught when it is not explicitly thrown by a method in the try\` block.
Mockito provides argument matchers and argument captors for flexibly stubbing or verifying method calls.
Mockito.verify(), Mockito.when(), Stubber.when() and BDDMockito.given() each have overloads with and without argument matchers.
However, if argument matchers or captors are used only on some of the parameters, all the parameters need to have matchers as well, otherwise an InvalidUseOfMatchersException will be thrown.
This rule consequently raises an issue every time matchers are not used on all the parameters of a stubbed/verified method.
The Thread class has some methods that are used to monitor and manage its execution. With the introduction of virtual threads in Java 21, there are three of these methods that behave differently between the standard platform threads and the virtual ones.
For virtual threads:
Thread.setDaemon(boolean) will throw an IllegalArgumentException if false is passed as an argument as a virtual thread daemon status is always true.
Thread.setPriority(int priority) will never change the actual priority of a virtual thread, which is always equal to Thread.NORM\_PRIORITY
Thread.getThreadGroup() will return a dummy "VirtualThreads" group that is empty and should not be used
This rule reports an issue when one of these methods is invoked on a virtual thread.
The likely intention of a user calling Thread.run() is to start the execution of code within a new thread. This, however, is not what happens when this method is called.
The purpose of Thread.run() is to provide a method that users can overwrite to specify the code to be executed. The actual thread is then started by calling Thread.start(). When Thread.run() is called directly, it will be executed as a regular method within the current thread.
To prevent URL spoofing, HostnameVerifier.verify() methods should do more than simply return true. Doing so may get you quickly past an exception, but that comes at the cost of opening a security hole in your application.
Non-abstract classes and enums with non-static, private members should explicitly initialize those members, either in a constructor or with a default value.
Naming a thread won’t make it run faster or more reliably, but it will make it easier to deal with if you need to debug the application.
In Java, value-based classes are those for which instances are final and immutable, like String, Integer and so on, and their identity relies on their value and not their reference. When a variable of one of these types is instantiated, the JVM caches its value, and the variable is just a reference to that value. For example, multiple String variables with the same value "Hello world!" will refer to the same cached string literal in memory.
The synchronized keyword tells the JVM to only allow the execution of the code contained in the following block to one Thread at a time. This mechanism relies on the identity of the object that is being synchronized between threads, to prevent that if object X is locked, it will still be possible to lock another object Y.
It means that the JVM will fail to correctly synchronize threads on instances of the aforementioned value-based classes, for instance:
In asynchronous testing, the test code is written in a way that allows it to wait for the asynchronous operation to complete before continuing with the test.
Using Thread.sleep in this case can cause flaky tests, slow test execution, and inaccurate test results. It creates brittle tests that can fail unpredictably depending on the environment or load.
Use mocks or libraries such as Awaitility instead. These tools provide features such as timeouts, assertions, and error handling to make it easier to write and manage asynchronous tests.
Before it reclaims storage from an object that is no longer referenced, the garbage collector calls finalize() on the object.
This is a good time to release resources held by the object.
Because the general contract is that the finalize method should only be called once per object, calling this method explicitly is misleading and does not respect this contract.
When two locks are held simultaneously, a wait call only releases one of them. The other will be held until some other thread requests a lock on the awaited object. If no unrelated code tries to lock on that object, then all other threads will be locked out, resulting in a deadlock.
Resources that can be reused across multiple invocations of the Lambda function should be initialized at construction time. For example in the constructor of the class, or in field initializers. This way, when the same container is reused for multiple function invocations, the existing instance can be reused, along with all resources stored in its fields. It is a good practice to reuse SDK clients and database connections by initializing them at class construction time, to avoid recreating them on every lambda invocation. Failing to do so can lead to performance degradation, and when not closed properly, even out of memory errors.
This rule reports an issue when the SDK client or the database connection is initialized locally inside a Lambda function.
Java 21 adds new String.indexOf methods that accept ranges (beginIndex, to endIndex) rather than just a start index. A StringIndexOutOfBounds can be thrown when indicating an invalid range, namely when:
beginIndex > endIndex (eg: beginIndex and endIndex arguments are mistakenly reversed)
beginIndex \< 0 (eg: because the older String.indexOf(what, fromIndex) accepts negative values)
An inner class that extends another type can call methods from both the outer class and parent type directly, without prepending super. or Outer.this..
When both the outer and parent classes contain a method with the same name, the compiler will resolve an unqualified call to the parent type’s implementation. The maintainer or a future reader may confuse the method call as calling the outer class’s implementation, even though it really calls the super type’s.
To make matters worse, the maintainer sees the outer class’s implementation in the same file as the call in the inner class, while the parent type is often declared in another file. The maintainer may not even be aware of the ambiguity present, as they do not see the parent’s implementation.
An XML External Entity or XSLT External Entity (XXE) vulnerability can occur when a \`javax.xml.transform.Transformer is created without enabling "Secure Processing" or when one is created without disabling resolving of both external DTDs and DTD entities. If that external data is being controlled by an attacker it may lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.
This rule raises an issue when a Transformer\` is created without either of these settings.
There is no need to declare a type parameter when naming a type constraint is not required. Using wildcards makes it easier to read.
Overriding a parent class method prevents that method from being called unless an explicit super call is made in the overriding method. In some cases, not calling the parent method is fine. However, setUp and tearDown provide some shared logic that is called before all test cases. This logic may change over the lifetime of your codebase. To make sure that your test cases are set up and cleaned up consistently, your overriding implementations of setUp and tearDown should call the parent implementations explicitly.
If you end up mocking every non-private method of a class in order to write tests, it is a strong sign that your test became too complex, or that you misunderstood the way you are supposed to use the mocking mechanism.
You should either refactor the test code into multiple units, or consider using the class itself, by either directly instantiating it, or creating a new one inheriting from it, with the expected behavior.
This rule reports an issue when every member of a given class are mocked.
AssertJ assertions \`allMatch and doesNotContains on an empty list always returns true whatever the content of the predicate. Despite being correct, you should make explicit if you expect an empty list or not, by adding isEmpty()/isNotEmpty() in addition to calling the assertion, or by testing the list’s content further. It will justify the useless predicate to improve clarity or increase the reliability of the test.
This rule raises an issue when any of the methods listed are used without asserting that the list is empty or not and without testing the content.
Targetted methods:
allMatch
allSatisfy
doesNotContain
doesNotContainSequence
doesNotContainSubsequence
doesNotContainAnyElementsOf\`
In Spring applications, application components that expose interfaces should be package protected at most, not public. Such reduced visibility helps ensure that the interface is only accessed through the container and not directly.
No matter whether the optional value is present or not, \`Optional::orElse's argument will always be executed. This is usually not what the developer intended when the content of the orElse() call has side effects. Even when no side effect is involved, the unnecessary computation of the orElse() clause might be a waste of resources.
Calls to Optional::orElse should be replaced with Optional::orElseGet whenever the alternative value is not a constant.
This rule raises an issue when Optional::orElse\` is called with an argument that doesn’t evaluate to a constant value.
Characters like 'é' can be expressed either as a single code point or as a cluster of the letter 'e' and a combining accent mark. Without the CANON\_EQ flag, a regex will only match a string in which the characters are expressed in the same way.
Calling Iterator.hasNext() is not supposed to have any side effects and hence should not change the iterator’s state. Iterator.next() advances the iterator by one item. So calling it inside Iterator.hasNext() breaks the hasNext() contract and will lead to unexpected behavior in production.
While you can use either forEach(list::add) or collect with a Stream, collect is by far the better choice because it’s automatically thread-safe and parallellizable.
Constructors should not access the values of fields that haven’t yet been initialized.
The contract of the Object.finalize() method is clear: only the Garbage Collector is supposed to call this method.
Making this method public is misleading, because it implies that any caller can use it.
\`getClass should not be used for synchronization in non-final classes because child classes will synchronize on a different object than the parent or each other, allowing multiple threads into the code block at once, despite the synchronized keyword.
Instead, hard code the name of the class on which to synchronize or make the class final\`.
Since assert statements aren’t executed by default (they must be enabled with JVM flags) developers should never rely on their execution the evaluation of any logic required for correct program function.
A for loop with a counter moving away from the end of the specified range is likely a programming mistake.
If the intention is to iterate over the specified range, this differs from what the loop does because the counter moves in the wrong direction.
If the intention is to have an infinite loop or a loop terminated only by a break statement, there are two problems:
The loop condition is not infinite because the counter variable will eventually overflow and fulfill the condition. This can take a long time, depending on the data type of the counter.
An infinite loop terminated by a break statement should be implemented using a while or do while loop to make the developer’s intention clear to the reader.
This rule allows banning usage of certain constructors.
The methods declared in an \`interface are public and abstract by default. Any variables are automatically public static final. Finally, class and interface are automatically public static. There is no need to explicitly declare them so.
Since annotations are implicitly interfaces, the same holds true for them as well.
Similarly, the final modifier is redundant on any method of a final class, private is redundant on the constructor of an Enum, and static is redundant for interface nested into a class or enum\`.
When testing exception via @Test annotation, having additional assertions inside that test method can be problematic because any code after the raised exception will not be executed. It will prevent you to test the state of the program after the raised exception and, at worst, make you misleadingly think that it is executed.
You should consider moving any assertions into a separate test method where possible, or using org.junit.Assert.assertThrows instead.
Alternatively, you could use try-catch idiom for JUnit version \< 4.13 or if your project does not support lambdas.
AssertJ assertions methods targeting the same object can be chained instead of using multiple \`assertThat. It avoids duplication and increases the clarity of the code.
This rule raises an issue when multiples assertThat\` target the same tested value.
Calling toString() or clone() on an object should always return a string or an object. Returning null instead contravenes the method’s implicit contract.
\`switch can contain a default clause for various reasons: to handle unexpected values, to show that all the cases were properly considered, etc.
For readability purposes, to help a developer quickly spot the default behavior of a switch statement, it is recommended to put the default clause at the end of the switch statement.
This rule raises an issue if the default clause is not the last one of the switch’s cases.
Java 7 introduced the ability to use a digit separator (\_) to split a literal number into groups of digits for better readability.
To ensure that readability is really improved by using digit separators, this rule verifies:
Homogeneity
Except for the left-most group, which can be smaller, all groups in a number should contain the same number of digits. Mixing group sizes is at best confusing for maintainers, and at worst a typographical error that is potentially a bug.
Standardization
It is also confusing to regroup digits using a size that is not standard. This rule enforce the following standards:
Decimal numbers should be separated using groups of 3 digits.
Hexadecimal numbers should be separated using groups of 2 or 4 digits.
Octal and Binary should be separated using groups of 2, 3 or 4 digits.
Furthermore, using groups with more than 4 consecutive digits is not allowed because they are difficult for maintainers to read.
By contract, fields in a Serializable class must themselves be either Serializable or transient. Even if the class is never explicitly serialized or deserialized, it is not safe to assume that this cannot happen. For instance, under load, most J2EE application frameworks flush objects to disk.
An object that implements Serializable but contains non-transient, non-serializable data members (and thus violates the contract) could cause application crashes and open the door to attackers. In general, a Serializable class is expected to fulfil its contract and not exhibit unexpected behaviour when an instance is serialized.
This rule raises an issue on:
Non-Serializable fields.
When a field is assigned a non-Serializable type within the class.
Collection fields when they are not private. Values that are not serializable could be added to these collections externally. Due to type erasure, it cannot be guaranteed that the collection will only contain serializable objects at runtime despite being declared as a collection of serializable types.
Using certain features of regular expressions, it is possible to create regular expressions that can never match or contain subpatterns that can never match. Since a pattern or sub-pattern that can never match any input is pointless, this is a sign that the pattern does not work as intended and needs to be fixed.
This rule finds some such regular expressions and subpatterns, specifically ones that meet one of the following conditions:
Beginning- and end-of-line/input boundaries appearing in a position where they can never match (e.g. an end-of-input marker being followed by other characters)
A back reference refers to a capturing group that will never be matched before the back reference
A \`serialVersionUID field is strongly recommended in all Serializable classes. If you do not provide one, one will be calculated for you by the compiler. The danger in not explicitly choosing the value is that when the class changes, the compiler will generate an entirely new id, and you will be suddenly unable to deserialize (read from file) objects that were serialized with the previous version of the class.
serialVersionUID's should be declared with all of these modifiers: static final long\`.
Abstract classes should not have public constructors. Constructors of abstract classes can only be called in constructors of their subclasses. So there is no point in making them public. The protected modifier should be enough.
A conditional operator is sometimes cluttering readability, if one of the operand is a boolean literal it can be simplified in a boolean expression :
Cloneable is the marker Interface that indicates that clone() may be called on an object. Overriding clone() without implementing Cloneable can be useful if you want to control how subclasses clone themselves, but otherwise, it’s probably a mistake.
Different formatters use different formatting symbols, and it can be easy to confuse one for the other. But get it wrong, and your output may be useless.
This rule logs an issue when the wrong type of format string is used for Guava, slf4j, logback or MessageFormat strings.
Since Java 7, \`Strings can be used as switch arguments. So when a single String is tested against three or more values in an if/else if structure, it should be converted to a switch instead for greater readability.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 7\`.
Comparisons of dissimilar types will always return false. The comparison and all its dependent code can simply be removed. This includes:
comparing an object with null
comparing an object with an unrelated primitive (E.G. a string with an int)
comparing unrelated classes
comparing an unrelated \`class and interface
comparing unrelated interface types
comparing an array to a non-array
comparing two arrays
Specifically in the case of arrays, since arrays don’t override Object.equals(), calling equals on two arrays is the same as comparing their addresses. This means that array1.equals(array2) is equivalent to array1==array2.
However, some developers might expect Array.equals(Object obj) to do more than a simple memory address comparison, comparing for instance the size and content of the two arrays. Instead, the == operator or Arrays.equals(array1, array2)\` should always be used with arrays.
Using a type parameter when you don’t have to simply obfuscates the code. Qualifying an inner type with a type parameter will compile, but confuse maintainers.
This rule allows you to track the use of the Checkstyle suppression comment mechanism.
HttpSession s are managed by web servers and can be serialized and stored on disk as the server manages its memory use in a process called "passivation" (and later restored during "activation").
Even though HttpSession does not extend Serializable, you must nonetheless assume that it will be serialized. If non-serializable objects are stored in the session, serialization might fail.
A cache is a long-lived object that holds references to shorter-lived objects. To prevent a cache from growing indefinitely, old objects the cache should be removed when they’re no longer used. This can be done with the use of soft references, which allow the garbage collector to remove unused cache entries when memory needs to be freed.
This rule raises an issue when a \`static collection does not use SoftReference.
Note that this rule is automatically disabled when the project’s sonar.java.source\` is lower than 7.
The Object#equals(Object obj) method is used to compare two objects to see if they are equal.
The obj parameter’s type is Object, this means that an object of any type can be passed as a parameter to this method.
Any class overriding Object#equals(Object obj) should respect this contract, accept any object as an argument, and return false when the argument’s type differs from the expected type. The obj parameter’s type can be checked using instanceof or by comparing the getClass() value:
The readObject method is implemented when a Serializable object requires special handling to be reconstructed from a file. The object created by readObject is accessed only by the thread that called the method, thus using the synchronized keyword in this context is unnecessary and causes confusion.
In Java 8, underscore (\_) cannot be used as a parameter to a lambda, and by Java 9, it’s a keyword. To ensure future portability (not to mention current readability), it should not be used now as an identifier.
According to the Java \`Comparable.compareTo(T o) documentation:
It is strongly recommended, but not strictly required that \`++(x.compareTo(y)==0)
notify and notifyAll both wake up sleeping threads waiting on the object’s monitor, but notify only wakes up one single thread, while notifyAll wakes them all up. Unless you do not care which specific thread is woken up, notifyAll should be used instead.
The \`java.util.function package provides a large array of functional interface definitions for use in lambda expressions and method references. In general it is recommended to use the more specialised form to avoid auto-boxing. For instance IntFunction\
This rule raises an issue when any of the following substitution is possible:
| Current Interface | Preferred Interface |
|---|---|
Function\ |
IntFunction\ |
Function\ |
LongFunction\ |
Function\ |
DoubleFunction\ |
Function\ |
DoubleToIntFunction |
Function\ |
DoubleToLongFunction |
Function\ |
LongToDoubleFunction |
Function\ |
LongToIntFunction |
Function\ |
ToIntFunction\ |
Function\ |
ToLongFunction\ |
Function\ |
ToDoubleFunction\ |
Function\ |
UnaryOperator\ |
BiFunction\ |
BinaryOperator\ |
Consumer\ |
IntConsumer |
Consumer\ |
DoubleConsumer |
Consumer\ |
LongConsumer |
BiConsumer\ |
ObjIntConsumer\ |
BiConsumer\ |
ObjLongConsumer\ |
BiConsumer\ |
ObjDoubleConsumer\ |
Predicate\ |
IntPredicate |
Predicate\ |
DoublePredicate |
Predicate\ |
LongPredicate |
Supplier\ |
IntSupplier |
Supplier\ |
DoubleSupplier |
Supplier\ |
LongSupplier |
Supplier\ |
BooleanSupplier |
UnaryOperator\ |
IntUnaryOperator |
UnaryOperator\ |
DoubleUnaryOperator |
UnaryOperator\ |
LongUnaryOperator |
BinaryOperator\ |
IntBinaryOperator |
BinaryOperator\ |
LongBinaryOperator |
BinaryOperator\ |
DoubleBinaryOperator |
Function\ |
Predicate\ |
BiFunction\ |
BiPredicate\ |
By accepting persistent entities as method arguments, the application allows clients to manipulate the object’s properties directly.
Validation is the first line of defense against injection, cross-site scripting, and many other attacks. Omitting it in modern web applications is simply negligent.
When creating a Struts ActionForm, you have the choice of extending something from the org.apache.struts.action package, or extending something from the org.apache.struts.validator package. Since you can’t use the Struts validator capabilities without extending something from the validator package, that should always be your choice.
If you go to the trouble of importing a symbol statically, then you should make use of it, and you should do so consistently. Similarly, there’s no reason to both import a class and then refer to it in code by its fully-qualified name. Otherwise, maintainers could be confused by the difference between qualified and unqualified references.
By contract, the NullCipher class provides an "identity cipher" - one that does not transform or encrypt the plaintext in any way. As a consequence, the ciphertext is identical to the plaintext. So this class should be used for testing, and never in production code.
Both \`FixedSizeList from the Commons library, and the list returned from Arrays.asList offer add and remove methods (as required by the List interface they implement), but neither truly supports their use. Both list types have fixed lengths and will throw errors if an add or remove method, or any of their variations, is called.
This rule raises an issue when one of the following methods is invoked on a FixedSizeList instance:
add
addAll
clear
remove
removeAll\`
When verifying that code raises a runtime exception, a good practice is to avoid having multiple method calls inside the tested code, to be explicit about which method call is expected to raise the exception.
It increases the clarity of the test, and avoid incorrect testing when another method is actually raising the exception.
Fields marked as transient in a Serializable class will be ignored during serialization and consequently not written out to a file (or stream).
This can be useful in situations such as where the content of a field can be recomputed from other fields. To reduce the output size, this field can be marked as transient and recomputed when a given object is deserialized.
Since transient is very specific to classes that implement Serializable, it is superfluous in classes that do not.
This rule raises an issue when a field is marked as transient, even though the containing class does not implement Serializable.
If you’ve gone to the trouble of writing an iterator method in a class that doesn’t implement Iterable, that trivial omission is costing you half the benefit of the method because you can’t use the class in enhanced for loops.
A Spring \`singleton bean may be used by many threads at once, and the use of instance (non-static) variables could cause concurrency issues.
This rule applies to classes with the following annotations: @Service, @Component, @Repository, @Scope("singleton")\`
Using boxed values in a ternary operator does not simply return one operand or the other based on the condition. Instead, the values are unboxed and coerced to a common type, which can result in a loss of precision when converting one operand from int to float or from long to double.
While this behavior is expected for arithmetic operations, it may be unexpected for the ternary operator. To avoid confusion or unexpected behavior, cast to a compatible type explicitly.
Once a value is known to be null or non-null, there’s no reason to re-check it unless it has been changed (or potentially changed) in the interim. Doing so anyway may may just be an over-abundance of caution, but it could indicate a bug.
There’s no valid reason to test this with instanceof. The only plausible explanation for such a test is that you’re executing code in a parent class conditionally based on the kind of child class this is. But code that’s specific to a child class should be in that child class, not in the parent.
The old, much-derided Date and Calendar classes have always been confusing and difficult to use properly, particularly in a multi-threaded context. JodaTime has long been a popular alternative, but now an even better option is built-in. Java 8’s JSR 310 implementation offers specific classes for:
| Class | Use for |
|---|---|
LocalDate |
a date, without time of day, offset, or zone |
LocalTime |
the time of day, without date, offset, or zone |
LocalDateTime |
the date and time, without offset, or zone |
OffsetDate |
a date with an offset such as +02:00, without time of day, or zone |
OffsetTime |
the time of day with an offset such as +02:00, without date, or zone |
OffsetDateTime |
the date and time with an offset such as +02:00, without a zone |
ZonedDateTime |
the date and time with a time zone and offset |
YearMonth |
a year and month |
MonthDay |
month and day |
Year/MonthOfDay/DayOfWeek/… |
classes for the important fields |
DateTimeFields |
stores a map of field-value pairs which may be invalid |
Calendrical |
access to the low-level API |
Period |
a descriptive amount of time, such as "2 months and 3 days" |
A for loop termination condition should test the loop counter against an invariant value that does not change during the execution of the loop. Invariant termination conditions make the program logic easier to understand and maintain.
This rule tracks three types of non-invariant termination conditions:
When the loop counters are updated in the body of the for loop
When the termination condition depends on a method call
When the termination condition depends on an object property since such properties could change during the execution of the loop.
Even if it is technically possible, Restricted Identifiers should not be used as identifiers. This is only possible for compatibility reasons, using it in Java code is confusing and should be avoided.
Note that this applies to any version of Java, including the one where these identifiers are not yet restricted, to avoid future confusion.
This rule reports an issue when restricted identifiers:
var
yield
record
are used as identifiers.
Collection.removeIf is more readable and less verbose than using the Iterator.remove idiom. It might also be more performant in some cases, particularly for ArrayList instances.
If the Service Provider does not manage to properly validate the incoming SAML response message signatures, attackers might be able to manipulate the response content without the application noticing. Especially, they might be able to alter the authentication-targeted user.
JDK7 introduced the class \`java.nio.charset.StandardCharsets. It provides constants for all charsets that are guaranteed to be available on every implementation of the Java platform.
ISO\_8859\_1
US\_ASCII
UTF\_16
UTF\_16BE
UTF\_16LE
UTF\_8
These constants should be preferred to:
the use of a String such as "UTF-8" which has the drawback of requiring the catch/throw of an UnsupportedEncodingException that will never actually happen
the use of Guava’s Charsets\` class, which has been obsolete since JDK7
The processHttpRequest method and methods called from it can be executed by multiple threads within the same servlet instance, and state changes to the instance caused by these methods are, therefore, not threadsafe.
This is due to the servlet container creating only one instance of each servlet (javax.servlet.http.HttpServlet) and attaching a dedicated thread to each incoming HTTP request. The same problem exists for org.apache.struts.action.Action but with different methods.
To prevent unexpected behavior, avoiding mutable states in servlets is recommended. Mutable instance fields should either be refactored into local variables or made immutable by declaring them final.
In Switch Expressions, an arrow label consisting of a block with a single \`yield can be simplified to directly return the value, resulting in cleaner code.
Similarly, for Switch Statements and arrow labels, a break in a block is always redundant and should not be used. Furthermore, if the resulting block contains only one statement, the curly braces of that block can also be omitted.
This rule reports an issue when a case of a Switch Expression contains a block with a single yield or when a Switch Statement contains a block with a break\`.
In a multi-threaded situation, un-\`synchronized lazy initialization of static fields could mean that a second thread has access to a half-initialized object while the first thread is still creating it. Allowing such access could cause serious bugs. Instead. the initialization block should be synchronized.
Similarly, updates of such fields should also be synchronized.
This rule raises an issue whenever a lazy static initialization is done on a class with at least one synchronized\` method, indicating intended usage in multi-threaded applications.
There’s no need to null-test a variable before an instanceof test because instanceof tests for null. Similarly, there’s no need to null-test a variable before dereferencing some other object.
Denoted by the "@" symbol, annotations are metadata that can be added to classes, methods, and variables for various purposes such as documentation, code analysis, and runtime processing.
Annotations have retention policies that determine in which context they are retained and available for use. There are three retention policies for annotations:
RetentionPolicy.SOURCE - Annotations are only available during compilation and code analysis. They are not included in the compiled class file and are not available at runtime. E.G. @Override, @SuppressWarnings
RetentionPolicy.CLASS - Annotations are included in the compiled class file providing information to the compiler, but they are not retained by the JVM at runtime. This is the default retention policy. E.G. @PreviewFeature
RetentionPolicy.RUNTIME - Annotations are included in the compiled class file and available at runtime. They can be accessed and used by the program through reflection. E.G. @FunctionalInterface, @Deprecated
It is important to understand that only annotations having the RUNTIME retention policy can be accessed at runtime using reflection. For example, the following if condition is true when the method argument is the java.util.function.Function class:
Before Java 8, a container annotation was required as wrapper to use multiple instances of the same annotation. As of Java 8, this is no longer necessary. Instead, these annotations should be used directly without a wrapper, resulting in cleaner and more readable code.
This rule is automatically disabled when the project’s sonar.java.source is lower than 8 as repeating annotations were introduced in Java 8.
Java 21 virtual threads allow the JVM to optimize the usage of OS threads, by mounting and unmounting them on an OS thread when needed, and making them more efficient when dealing with blocking operations such as HTTP requests or I/O.
However, when code is executed inside a synchronized block or synchronized method, the virtual thread stays pinned to the underlying OS thread and cannot be unmounted during a blocking operation. This will cause the OS thread to be blocked, which can impact the scalability of the application.
Therefore, virtual threads should not execute code that contains synchronized blocks or invokes synchronized methods. Platform threads should be used in these cases.
This rule raises an issue when a virtual thread contains synchronized blocks or invokes synchronized methods.
According to the Java documentation, any implementation of the \`InputSteam.read() method is supposed to read the next byte of data from the input stream. The value byte must be an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned.
But in Java, the byte primitive data type is an 8-bit signed two’s complement integer. It has a minimum value of -128 and a maximum value of 127. So by contract, the implementation of an InputSteam.read() method should never directly return a byte\` primitive data type. A conversion into an unsigned byte must be done before by applying a bitmask.
Setting the wrong Content-Type for a response can leave an application vulnerable to cross-site scripting attacks. Specifically, JSON should always be served with the \`application/json Content-Type.
This rule checks the Content-Type of responses containing classes in the org.json and javax.json\` packages.
Hibernate’s lazy loading allows you to retrieve just the data of the current class without being forced to load all its related classes. For instance with lazy loading, you can pull up an instance of a \`Lecture @Entity without being forced to load all its Students.
But that’s only if you’re storing the Students in a collection. Store them in an array instead, and the benefits of lazy loading are no longer available.
This rule raises an issue on each array in @Entity\` classes.
Configured URL matchers are considered in the order they are declared. Especially, for a given resource, if a looser filter is defined before a stricter one, only the less secure configuration will apply. No request will ever reach the stricter rule.
This rule raises an issue when:
A URL pattern ending with \*\* precedes another one having the same prefix. E.g. /admin/\*\* is defined before /admin/example/\*\*
A pattern without wildcard characters is preceded by another one that matches it. E.g.: /page-index/db is defined after /page\*/\*\*
\`ThreadLocal variables are supposed to be garbage collected once the holding thread is no longer alive. Memory leaks can occur when holding threads are re-used which is the case on application servers using pool of threads.
To avoid such problems, it is recommended to always clean up ThreadLocal variables using the remove() method to remove the current thread’s value for the ThreadLocal variable.
In addition, calling set(null) to remove the value might keep the reference to this pointer in the map, which can cause memory leak in some scenarios. Using remove\` is safer to avoid this issue.
Shared naming conventions allow teams to collaborate efficiently.
This rule raises an issue when a method name does not match a provided regular expression.
For example, with the default provided regular expression ^\[a-z]\[a-zA-Z0-9]\*\$, the method:
The Reader.read() and the BufferedReader.readLine() are used for reading data from a data source. The return value of these methods is the data read from the data source, or null when the end of the data source is reached. If the return value is ignored, the data read from the source is thrown away and may indicate a bug.
This rule raises an issue when the return values of Reader.read() and BufferedReader.readLine() and their subclasses are ignored or merely null-checked.
Unlike similar AssertJ methods testing exceptions (\`assertThatCode(), assertThatExceptionOfType(), …), the assertThatThrownBy() method can be used alone, failing if the code did not raise any exception.
Still, only testing that an exception was raised is not enough to guarantee that it was the expected one, and you should test the exception type or content further. In addition, it will make explicit what you are expecting, without relying on side-effects.
This rule raises an issue when assertThatThrownBy\` is used, without testing the exception further.
JUnit assertions should not be made from the run method of a Runnable, because their failure may not be detected in the test that initiated them. Failed assertions throw assertion errors. However, if the error is thrown from another thread than the one that initiated the test, the thread will exit but the test will not fail.
Having too many return statements in a method increases the method’s essential complexity because the flow of execution is broken each time a return statement is encountered. This makes it harder to read and understand the logic of the method.
Java 7’s try-with-resources structure automatically handles closing the resources that the try itself opens. Thus, adding an explicit close() call is redundant and potentially confusing.
In records, introduced in Java 16, there are 2 ways to write a custom constructor: canonical and compact.
A canonical constructor is an ordinary constructor with arguments for all private fields. The default implementation just provides initialization for all private fields and there is no need to write it manually. You might want to write it yourself when you need to customize the constructor logic.
A compact constructor doesn’t have parameters defined explicitly, parentheses are omitted and access to private fields is not possible (even via this). The compact constructor has access to the constructor’s arguments and its body is executed right before the field initialization. It’s a perfect place to provide validation.
This rule reports an issue when a canonical constructor can be easily replaced by a compact version when these requirements are met:
the last statements are trivial field initializations
no statement reads from fields or components
there are other statements in the constructor (case covered by S6207: redundant constructors in records)
The repetition of a unary operator is usually a typo. The second operator invalidates the first one in most cases:
Non final classes shouldn’t use a hardcoded class name in the equals method. Doing so breaks the method for subclasses. Instead, make the comparison dynamic.
In Records, serialization is not done the same way as for ordinary serializable or externalizable classes. The serialized representation of a record object will be a sequence of values (record components). During the deserialization of records, the stream of components is read and components are constructed. Then the record object is recreated by invoking the record’s canonical constructor with the component values serving as arguments (or default values for absent arguments).
This process cannot be customized, so any class-specific \`writeObject, readObject, readObjectNoData, writeExternal, and readExternal methods or serialPersistentFields fields in record classes are ignored during serialization and deserialization.
However, there is a way to substitute serialized/deserialized objects in writeReplace and readResolve.
This rule raises an issue when any of writeObject, readObject, readObjectNoData, writeExternal, readExternal or serialPersistentFields\` are present as members in a Record class.
Java 21 introduces case null for switch. It is a more concise and readable way to handle nullability compared to an if statement before a switch.
When the application does not implement controls over the JMS object types, its clients could be able to force the deserialization of arbitrary objects. This may lead to deserialization injection attacks.
StringBuffer and StringBuilder instances that are appended but never toStringed needlessly clutter the code, and worse are a drag on performance. Either they should be removed, or the missing toString call added.
When using the \`Stream API, call chains should be simplified as much as possible. Not only does it make the code easier to read, it also avoid creating unnecessary temporary objects.
This rule raises an issue when one of the following substitution is possible:
| Original | Preferred |
|---|---|
stream.filter(predicate).findFirst().isPresent() |
stream.anyMatch(predicate) |
stream.filter(predicate).findAny().isPresent() |
stream.anyMatch(predicate) |
!stream.anyMatch(predicate) |
stream.noneMatch(predicate) |
!stream.anyMatch(x -> !(...)) |
stream.allMatch(...) |
stream.map(mapper).anyMatch(Boolean::booleanValue) |
stream.anyMatch(predicate)\` |
java.lang.Error and its subclasses represent abnormal conditions, such as OutOfMemoryError, which should only be encountered by the Java Virtual Machine.
A common reason for a poorly performant query is because it’s processing more data than required.
Querying unnecessary data demands extra work on the server, adds network overhead, and consumes memory and CPU resources on the application server. The effect is amplified when the query includes multiple joins.
The rule flags an issue when a SELECT \* query is provided as an argument to methods in java.sql.Connection and java.sql.Statement.
Objects annotated with Mockito annotations \`@Mock, @Spy, @Captor, or @InjectMocks need to be initialized explicitly.
There are several ways to do this:
Call MockitoAnnotations.openMocks(this) or MockitoAnnotations.initMocks(this) in a setup method
Annotate test class with @RunWith(MockitoJUnitRunner.class) (JUnit 4)
Annotate test class with @ExtendWith(MockitoExtension.class) (JUnit 5 Jupiter)
Use @Rule public MockitoRule rule = MockitoJUnit.rule();
Test using uninitialized mocks will fail.
Note that this only applies to annotated Mockito objects. It is not necessary to initialize objects instantiated via Mockito.mock() or Mockito.spy()\`.
This rule raises an issue when a test class uses uninitialized mocks.
Some mathematical operations are unnecessary and should not be performed because their results are predictable.
For instance, anyValue % 1 will always return 0, as any integer value can be divided by 1 without remainder.
Similarly, casting a non-floating-point to a floating-point value and then passing it to Math.round, Math.ceil, or Math.floor is also unnecessary, as the result will always be the original value.
The following operations are unnecessary when given any constant value: Math.abs, Math.ceil, Math.floor, Math.rint, Math.round. Instead, use the result of the operation directly.
The following operations are unnecessary with certain constants and can be replaced by the result of the operation directly:
| Operation | Value |
|---|---|
acos |
0.0 or 1.0 |
asin |
0.0 or 1.0 |
atan |
0.0 or 1.0 |
atan2 |
0.0 |
cbrt |
0.0 or 1.0 |
cos |
0.0 |
cosh |
0.0 |
exp |
0.0 or 1.0 |
expm1 |
0.0 |
log |
0.0 or 1.0 |
log10 |
0.0 or 1.0 |
sin |
0.0 |
sinh |
0.0 |
sqrt |
0.0 or 1.0 |
tan |
0.0 |
tanh |
0.0 |
toDegrees |
0.0 or 1.0 |
toRadians |
0.0 |
The Spring framework’s @RestController annotation is equivalent to using the @Controller and @ResponseBody annotations together. As such, it is redundant to add a @ResponseBody annotation when the class is already annotated with @RestController.
Passing single null or primitive array argument to the variable arity method may not work as expected. In the case of null, it is not passed as array with single element, but the argument itself is null. In the case of a primitive array, if the formal parameter is Object..., it is passed as a single element array. This may not be obvious to someone not familiar with such corner cases, and it is probably better to avoid such ambiguities by explicitly casting the argument to the desired type.
@VisibleForTesting can be used to mark methods, fields and classes whose visibility restrictions have been relaxed more than necessary for the API to allow for easier unit testing.
Access to such methods, fields and classes only possible thanks to this relaxed visibility is fine for test code, but it should be avoided in production code. In production code these methods should be treated as if they are private.
Supported framework:
Guava: \`com.google.common.annotations.VisibleForTesting
AssertJ: org.assertj.core.util.VisibleForTesting
Android: androidx.annotation.VisibleForTesting
Apache Flink: org.apache.flink.annotation.VisibleForTesting
or any other annotation named VisibleForTesting\`
Java 15 introduced feature of \`sealed classes. With sealed classes and interfaces you can specify a strict hierarchy of types and restrict possible inheritance.
Although this feature can help to make code safer, it is not applicable everywhere. Functional interfaces can not be sealed. This means that if an interface with a single abstract method is declared with a sealed keyword, its implementation can’t be replaced with a lambda.
This rule reports an issue when an interface with a single abstract method is marked sealed\`.
When List.remove() is called, the list shrinks, and the indices of all elements following the removed element are decremented by one. If this operation is performed within a loop that iterates through the elements in ascending order, it will cause the loop to skip the element immediately following the removed element.
According to the EJB specification, EJB’s:
…must not attempt to create a class loader; obtain the current class loader; set the context class loader…
This rule raises an issue each time an EJB obtains a class loader.
Overriding a parent class' method implementation with an \`abstract method is a terrible practice for a number of reasons:
it blocks invocation of the original class' method by children of the abstract class.
it requires the abstract\` class' children to re-implement (copy/paste?) the original class' logic.
it violates the inherited contract.
In Java, the Thread class represents a thread of execution. Synchronization between threads is typically achieved using objects or shared resources.
The methods wait(…), notify(), and notifyAll() are related to the underlying object’s monitor and are designed to be called on objects that act as locks or monitors for synchronization. These methods are available on Java Object and, therefore, automatically inherited by all objects, including Thread.
Calling these methods on a Thread may corrupt the behavior of the JVM, which relies on them to change the state of the thread (BLOCKED, WAITING,…).
An equals method that unconditionally returns the same answer is an error likely to cause many bugs.
When using null-related annotations at global scope level, for instance using \`javax.annotation.ParametersAreNonnullByDefault (from JSR-305) at package level, it means that all the parameters to all the methods included in the package will, or should, be considered Non-null. It is equivalent to annotating every parameter in every method with non-null annotations (such as @Nonnull).
The rule raises an issue every time a parameter could be null\` for a method invocation, where the method is annotated as forbidding null parameters.
Calling an overridable method from a constructor could result in failures or strange behaviors when instantiating a subclass which overrides the method.
For example:
The subclass class constructor starts by contract by calling the parent class constructor.
The parent class constructor calls the method, which has been overridden in the child class.
If the behavior of the child class method depends on fields that are initialized in the child class constructor, unexpected behavior (like a NullPointerException) can result, because the fields aren’t initialized yet.
\`Optional value can hold either a value or not. The value held in the Optional can be accessed using the get() method, but it will throw a
NoSuchElementException if there is no value present. To avoid the exception, calling the isPresent() or ! isEmpty() method should always be done before any call to get().
Alternatively, note that other methods such as orElse(...), orElseGet(...) or orElseThrow(...) can be used to specify what to do with an empty Optional\`.
Throwing generic exceptions such as \`Error, RuntimeException, Throwable, and Exception will have a negative impact on any code trying to catch these exceptions.
From a consumer perspective, it is generally a best practice to only catch exceptions you intend to handle. Other exceptions should ideally be let to propagate up the stack trace so that they can be dealt with appropriately. When a generic exception is thrown, it forces consumers to catch exceptions they do not intend to handle, which they then have to re-throw.
Besides, when working with a generic type of exception, the only way to distinguish between multiple exceptions is to check their message, which is error-prone and difficult to maintain. Legitimate exceptions may be unintentionally silenced and errors may be hidden.
For instance, when a Throwable is caught and not re-thrown, it may mask errors such as OutOfMemoryError\` and prevent the program from terminating gracefully.
When throwing an exception, it is therefore recommended to throw the most specific exception possible so that it can be handled intentionally by consumers.
Well-named functions can allow the users of your code to understand at a glance what to expect from the function - even before reading the documentation. Toward that end, methods returning a boolean should have names that start with "is" or "has" rather than with "get".
The ability to map a class to a database table has made database interaction in Java a lot easier. But map multiple classes to the same table and you’ll end up with a classic case of the left hand not knowing what the right hand is doing. In the worse case scenario, it could lead to serious data corruption.
This rule raises an issue when multiple classes are mapped to the same table with Hibernate or JPA annotations.
When using POSIX classes like \`\p\{Alpha} without the UNICODE\_CHARACTER\_CLASS flag or when using hard-coded character classes like "\[a-zA-Z]", letters outside of the ASCII range, such as umlauts, accented letters or letter from non-Latin languages, won’t be matched. This may cause code to incorrectly handle input containing such letters.
To correctly handle non-ASCII input, it is recommended to use Unicode classes like \p\{IsAlphabetic}. When using POSIX classes, Unicode support should be enabled by either passing Pattern.UNICODE\_CHARACTER\_CLASS as a flag to Pattern.compile or by using (?U)\` inside the regex.
Testing equality or nullness with JUnit’s assertTrue() or assertFalse() should be simplified to the corresponding dedicated assertion.
Using \`File.createTempFile as the first step in creating a temporary directory causes a race condition and is inherently unreliable and insecure. Instead, Files.createTempDirectory (Java 7+) or a library function such as Guava’s similarly-named Files.createTempDir should be used.
This rule raises an issue when the following steps are taken in immediate sequence:
call to File.createTempFile
delete resulting file
call mkdir on the File object
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 7\`.
It is not uncommon, for instance when dealing with SQL requests, to have repeated calls to StringBuilder.append() to create a long (sometimes really long) String that will be then passed to the appropriate subsystem (e.g. jdbc.Statement()). This is very undesirable because it makes it more difficult to read, and maintain, the statement in the String due to overlapping syntaxes.
It is highly recommended to address such a case with an external text file loaded as a resource.
The purpose of the @Value annotation in org.springframework.beans.factory.annotation is to inject a value into a field or method based on the Spring context after it has been established.
If the annotation does not include an expression (either Spring Expression Language or a property injection), the injected value is a simple constant that does not depend on the Spring context, making the annotation replaceable with a standard field initialization statement.
This not only implies the redundant use of @Value, but could also indicate an error where the expression indicators (#, \$) were omitted by mistake.
For maximum reusability, methods should accept parameters with as little specialization as possible. So unless specific features from a child class are required by a method, a type higher up the class hierarchy should be used instead.
Because printf-style format strings are interpreted at runtime, rather than validated by the Java compiler, they can contain errors that lead to unexpected behavior or runtime errors. This rule statically validates the good behavior of printf-style formats when calling the format(...) methods of java.util.Formatter, java.lang.String, java.io.PrintStream, MessageFormat, and java.io.PrintWriter classes and the printf(...) methods of java.io.PrintStream or java.io.PrintWriter classes.
ThreadPoolExecutor is an object that efficiently manages and controls the execution of multiple tasks in a thread pool. A thread pool is a collection of pre-initialized threads ready to execute tasks. Instead of creating a new thread for each task, which can be costly in terms of system resources, a thread pool reuses existing threads.
java.util.concurrent.ScheduledThreadPoolExecutor is an extension of ThreadPoolExecutor that can additionally schedule commands to run after a given delay or to execute periodically.
ScheduledThreadPoolExecutor 's pool is sized with corePoolSize, so setting corePoolSize to zero means the executor will have no threads and run nothing. corePoolSize should have a value greater than zero and valid for your tasks.
This rule detects instances where corePoolSize is set to zero via its setter or the object constructor.
The request handler function in a Controller should set the appropriate HTTP status code based on the operation’s success or failure. This is done by returning a Response object with the appropriate status code.
If an exception is thrown during the execution of the handler, the status code should be in the range of 4xx or 5xx. Examples of such codes are BAD\_REQUEST, UNAUTHORIZED, FORBIDDEN, NOT\_FOUND, INTERNAL\_SERVER\_ERROR, BAD\_GATEWAY, SERVICE\_UNAVAILABLE, etc.
The status code should be 1xx, 2xx, or 3xx if no exception is thrown and the operation is considered successful. Such codes include OK, CREATED, MOVED\_PERMANENTLY, FOUND, etc.
Java offers a built-in serialization mechanism for classes that implement the Serializable interface. The developer can either rely on Java’s default serialization and deserialization logic or implement custom methods for these tasks. The JVM will use methods such as readObject and writeObject to execute custom behavior. This only works, however, if these methods match exactly the expected signatures. If they do not, the JVM will fall back to the default logic, resulting in unexpected behavior at runtime, while the developer believes that the default logic has been overidden.
This rule raises an issue if an implementation of writeObject, readObject, readObjectNoData, writeReplace, or readResolve has an incorrect access modifier, return type, or is not static when it should be (and vice-versa).
In certain Android methods, calls to the \`super version of the method should always come first. Otherwise, you risk leaving the job half-done.
This rule raises an issue when the following Activity methods do not begin with a call to super:
onCreate
onConfigurationChanged
onPostCreate
onPostResume
onRestart
onRestoreInstanceState
onResume
onStart\`
Classes annotated as @Controller in Spring are responsible for handling incoming web requests. When annotating methods or the entire controller with @ResponseBody, the return value of said methods will be serialized and set as the response body. In other words, it tells the Spring framework that this method does not produce a view. This mechanism is commonly used to create API endpoints.
Spring provides @RestController as a convenient annotation to replace the combination of @Controller and @ResponseBody. The two are functionally identical, so the single annotation approach is preferred.
This rule will raise an issue on a class that is annotated with @Controller if:
the class is also annotated with @ResponseBody or
all methods in said class are annotated with @ResponseBody.
Calling System.exit(int status) or Rutime.getRuntime().exit(int status) calls the shutdown hooks and shuts downs the entire Java virtual machine. Calling Runtime.getRuntime().halt(int) does an immediate shutdown, without calling the shutdown hooks, and skipping finalization.
Each of these methods should be used with extreme care, and only when the intent is to stop the whole Java process. For instance, none of them should be called from applications running in a J2EE container.
This rule is not really a rule, but a demonstration of the features from Asciidoc that can appear in a rule description.
More specifically, its "How to fix it" section contains several frameworks.
By default case insensitivity only affects letters in the ASCII range. This can be changed by either passing Pattern.UNICODE\_CASE or Pattern.UNICODE\_CHARACTER\_CLASS as an argument to Pattern.compile or using (?u) or (?U) within the regex.
If not done, regular expressions involving non-ASCII letters will still handle those letters as being case sensitive.
Most checks against an indexOf value compare it with -1 because 0 is a valid index. Checking against > 0 ignores the first element, which is likely a bug.
Generic types (types with type parameters) have been introduced into Java with language version 1.5. If type parameters are specified for a class or method, it is still possible to ignore them to keep backward compatibility with older code, which is called the raw type of the class or interface.
Using raw type expressions is highly discouraged because the compiler cannot perform static type checking on them. This means that the compiler will not report typing errors about them at compile time, but a ClassCastException will be thrown during runtime.
In Java 1.5, generics were also added to the Java collections API, and the data structures in java.util, such as List, Set, or Map, now feature type parameters. Collections.EMPTY\_LIST, Collections.EMPTY\_SET, and Collections.EMPTY\_MAP are relics from before generics, and they return raw lists, sets, or maps, with the limitations mentioned above.
Iterating over a collection using a for-each loop in Java relies on iterators.
An iterator is an object that allows you to traverse a collection of elements, such as a list or a dictionary. Iterators are used in for-each loops to iterate over the elements of a collection one at a time.
It is important to note that iterators are designed to be read-only. Modifying a collection while iterating over it can cause unexpected behavior, as the iterator may skip over or repeat elements. Therefore, it is important to avoid modifying a collection while iterating over it to ensure that your code behaves as expected.
Most JDK collection implementations don’t support such modification and may throw a ConcurrentModificationException. Even if no such exception is thrown, attempting to modify a collection during iteration could be the source of incorrect or unspecified behaviors in the code.
If you still want to modify the collection, it is best to refactor the code and use a second collection (e.g by using streams and filter operations).
The BigDecimal is used to represents immutable, arbitrary-precision signed decimal numbers.
Differently from the BigDecimal, the double primitive type and the Double type have limited precision due to the use of double-precision 64-bit IEEE 754 floating point. Because of floating point imprecision, the BigDecimal(double) constructor can be somewhat unpredictable.
For example writing new BigDecimal(0.1) doesn’t create a BigDecimal which is exactly equal to 0.1, but it is equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length).
Primitives can be read and written to atomically. Except for \`long and double, that is. These 64-bit primitives must be marked volatile in multi-threaded environments, or swapped out for their atomic counterparts: AtomicLong, and AtomicDouble to guarantee that their updates are always visible to other threads.
Similarly, to ensure that updates to 32-bit primitives are visible to all threads, they should also be marked volatile\`.
In regular expressions the escape sequence \`\cX, where the X stands for any character that’s either @, any capital ASCII letter, \[, , ], ^ or \_, represents the control character that "corresponds" to the character following \c, meaning the control character that comes 64 bytes before the given character in the ASCII encoding.
In some other regex engines (for example in that of Perl) this escape sequence is case insensitive and \cd produces the same control character as \cD. Further using \c with a character that’s neither @, any ASCII letter, \[, , ], ^ nor \_, will produce a warning or error in those engines. Neither of these things is true in Java, where the value of the character is always XORed with 64 without checking that this operation makes sense. Since this won’t lead to a sensible result for characters that are outside of the @ to \_ range, using \c\` with such characters is almost certainly a mistake.
This rule raises an issue when:
a JavaMail’s \`javax.mail.Session is created with a Properties object having no mail.smtp.ssl.checkserveridentity or mail.smtps.ssl.checkserveridentity not configured to true
a Apache Common Emails’s org.apache.commons.mail.SimpleEmail is used with setSSLOnConnect(true) or setStartTLSEnabled(true) or setStartTLSRequired(true) without a call to setSSLCheckServerIdentity(true)\`
The battery life is a major concern for mobile devices and choosing the right Sensor is very important to reduce the power usage and extend the battery life.
It is recommended, for reducing the power usage, to use TYPE\_GEOMAGNETIC\_ROTATION\_VECTOR for background tasks, long-running tasks and other tasks not requiring accurate motion detection.
The rule reports an issue when android.hardware.SensorManager#getDefaultSensor uses TYPE\_ROTATION\_VECTOR instead of TYPE\_GEOMAGNETIC\_ROTATION\_VECTOR.
Spring beans belonging to packages that are not included in a \`@ComponentScan configuration will not be accessible in the Spring Application Context. Therefore, it’s likely to be a configuration mistake that will be detected by this rule.
Note: the @ComponentScan is implicit in the @SpringBootApplication\` annotation, case in which Spring Boot will auto scan for components in the package containing the Spring Boot main class and its sub-packages.
Java’s garbage collection cannot be relied on to clean up everything. Specifically, subclasses of \`org.eclipse.swt.graphics.Resource must be manually dispose()-ed when you’re done with them.
Particularly for the Image subclass, which retains an open FileHandle for the life of the instance, failure to properly dispose of Resource\`s can result in a resource leak which could bring first the application and then perhaps the box it’s on to their knees.
The use of org.fest.assertions.Assertions.assertThat by itself does nothing. You must combine it with another method that actually tests the value in use.
When the call to a function doesn’t have any side effects, what is the point of making the call if the results are ignored? In such case, either the function call is useless and should be dropped or the source code doesn’t behave as expected.
To prevent generating any false-positives, this rule triggers an issue only on the following predefined list of immutable classes in the Java API :
\`java.lang.String
java.lang.Boolean
java.lang.Integer
java.lang.Double
java.lang.Float
java.lang.Byte
java.lang.Character
java.lang.Short
java.lang.StackTraceElement
java.time.DayOfWeek
java.time.Duration
java.time.Instant
java.time.LocalDate
java.time.LocalDateTime
java.time.LocalTime
java.time.Month
java.time.MonthDay
java.time.OffsetDateTime
java.time.OffsetTime
java.time.Period
java.time.Year
java.time.YearMonth
java.time.ZonedDateTime
java.math.BigInteger
java.math.BigDecimal
java.util.Optional
As well as methods of the following classes:
java.util.Collection:
size()
isEmpty()
contains(...)
containsAll(...)
iterator()
toArray()
java.util.Map:
size()
isEmpty()
containsKey(...)
containsValue(...)
get(...)
getOrDefault(...)
keySet()
entrySet()
values()
java.util.stream.Stream
toArray
reduce
collect
min
max
count
anyMatch
allMatch
noneMatch
findFirst
findAny
toList\`
When a type variable or a wildcard declares an upper bound that is final, the parametrization is not generic at all because it accepts one and only one type at runtime: the one that is final. Instead of using Generics, it’s simpler to directly use the concrete final class.
By default, the Maven Surefire plugin only executes test classes with names that end in "Test" or "TestCase". Name your class "TestClassX.java", for instance, and it will be skipped.
This rule raises an issue for each test class with a name not ending in "Test" or "TestCase".
In Java 16 \`records are finalized and can be safely used in production code. Records represent immutable read-only data structure and should be used instead of creating immutable classes. Immutability of records is guaranteed by the Java language itself, while implementing immutable classes on your own might lead to some bugs.
One of the important aspects of records\` is that final fields can’t be overwritten using reflection.
This rule reports an issue on classes for which all these statements are true:
all instance fields are private and final
has only one constructor with a parameter for all fields
has getters for all fields
Deserialization takes a stream of bits and turns it into an object. If the stream contains the type of object you expect, all is well. But if you’re deserializing untrusted input, and an attacker has inserted some other type of object, you’re in trouble. Why? There are a few different attack scenarios, but one widely-documented one goes like this: Deserialization first instantiates an \`Object, then uses the readObject method to populate it. If the attacker has overridden readObject then he is entirely in control of what code executes during that process. It is only after readObject has completed that your newly-minted Object can be cast to the type you expected. A ClassCastException or ClassNotFoundException will be thrown, but at that point it’s too late.
To prevent this, you should either use look-ahead deserialization (pre-Java 9) or filtering to make sure you’re dealing with the correct type of object before you act on it.
Several third-party libraries offer look-ahead deserialization, including:
ikkisoft’s SerialKiller
Apache Commons Class IO’s ValidatingObjectInputStream
contrast-rO0’s SafeObjectInputStream\`
Note that it is possible to set a deserialization filter at the level of the JVM, but relying on that requires that your environment be configured perfectly. Every time. Additionally, such a filter may have unwanted impacts on other applications in the environment. On the other hand, setting a filter as close as possible to the deserialization that uses it allows you to specify a very narrow, focused filter.
Some implementations of java.sql.ResultSet#getMetaData() suffer from performance issue and should not be called in a loop. Instead, multiple calls in a row should be replaced by a single cached call.
In Java 14 there is a new way to write cases in Switch Statement and Expression when the same action should be performed for different cases. Instead of declaring multiples branches with the same action, you can combine all of them in a single case group, separated with commas. It will result in a more concise code and improved readability.
This rule reports an issue when multiple cases in a Switch can be grouped into a single comma-separated case.
There’s no need to invoke stream() on a Collection before a forEach call because each Collection has its own forEach method.
An \`assert is inappropriate for parameter validation because assertions can be disabled at runtime in the JVM, meaning that a bad operational setting would completely eliminate the intended checks. Further, asserts that fail throw AssertionErrors, rather than throwing some type of Exception. Throwing Errors is completely outside of the normal realm of expected catch/throw behavior in normal programs.
This rule raises an issue when a public method uses one or more of its parameters with assert\`s.
Synchronizing at the method, rather than the block level could lead to problems when maintenance adds code to the method, perhaps inadvertently synchronizing it as well. Instead, synchronization should be applied to the smallest feasible block for optimum performance and maintainability.
The MD5 algorithm and its successor, SHA-1, are no longer considered secure, because it is too easy to create hash collisions with them. That is, it takes too little computational effort to come up with a different input that produces the same MD5 or SHA-1 hash, and using the new, same-hash value gives an attacker the same access as if he had the originally-hashed value. This applies as well to the other Message-Digest algorithms: MD2, MD4, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160.
The following APIs are tracked for use of obsolete crypto algorithms:
\`java.security.AlgorithmParameters (JDK)
java.security.AlgorithmParameterGenerator (JDK)
java.security.MessageDigest (JDK)
java.security.KeyFactory (JDK)
java.security.KeyPairGenerator (JDK)
java.security.Signature (JDK)
javax.crypto.Mac (JDK)
javax.crypto.KeyGenerator (JDK)
org.apache.commons.codec.digest.DigestUtils (Apache Commons Codec)
org.springframework.util.DigestUtils
com.google.common.hash.Hashing (Guava)
org.springframework.security.authentication.encoding.ShaPasswordEncoder (Spring Security 4.2.x)
org.springframework.security.authentication.encoding.Md5PasswordEncoder (Spring Security 4.2.x)
org.springframework.security.crypto.password.LdapShaPasswordEncoder (Spring Security 5.0.x)
org.springframework.security.crypto.password.Md4PasswordEncoder (Spring Security 5.0.x)
org.springframework.security.crypto.password.MessageDigestPasswordEncoder (Spring Security 5.0.x)
org.springframework.security.crypto.password.NoOpPasswordEncoder (Spring Security 5.0.x)
org.springframework.security.crypto.password.StandardPasswordEncoder\` (Spring Security 5.0.x)
Consider using safer alternatives, such as SHA-256, SHA-3 or adaptive one way functions like bcrypt or PBKDF2.
An interface that consists solely of constant definitions is a bad practice. The purpose of interfaces is to provide an API, not implementation details. That is, they should provide functions in the first place and constants only to assist these functions, for example, as possible arguments.
If an interface contains constants only, move them either to somewhere else, or replace the interface with an Enum or a final class with a private constructor.
Failing to explicitly declare the visibility of a member variable could result it in having a visibility you don’t expect, and potentially leave it open to unexpected modification by other classes.
The default access level modifier may be intentional; in that case, this rule can report false positives.
Mutable objects are those whose state can be changed. For instance, an array is mutable, but a String is not. Private mutable class members should never be returned to a caller or accepted and stored directly. Doing so leaves you vulnerable to unexpected changes in your class state.
Instead use an unmodifiable Collection (via Collections.unmodifiableCollection, Collections.unmodifiableList, …) or make a copy of the mutable object, and store or return the copy instead.
This rule checks that private arrays, collections and Dates are not stored or returned directly.
\`@ComponentScan is used to determine which Spring Beans are available in the application context. The packages to scan can be configured thanks to the basePackageClasses or basePackages (or its alias value) parameters. If neither parameter is configured, @ComponentScan will consider only the package of the class annotated with it. When @ComponentScan is used on a class belonging to the default package, the entire classpath will be scanned.
This will slow-down the start-up of the application and it is likely the application will fail to start with an BeanDefinitionStoreException because you ended up scanning the Spring Framework package itself.
This rule raises an issue when:
@ComponentScan, @SpringBootApplication and @ServletComponentScan are used on a class belonging to the default package
@ComponentScan\` is explicitly configured with the default package
The use of shorts saves a little bit of memory, but actually increases processor use because the JVM has no real capability for handling shorts. Instead, it must convert each short to an int before performing any operations on it, then convert it back to a short for storage.
Many existing switch statements are essentially simulations of switch expressions, where each arm either assigns to a common target variable or returns a value. Expressing this as a statement is roundabout, repetitive, and error-prone.
Java 14 added support for switch expressions, which provide more succinct and less error-prone version of switch.
A hardcoded file path is a guarantee that eventually the program will fail. It may happen because the paths on the target machine changed or because the application was deployed on an OS other than the one on which it was developed. After all, not every OS has a "C:" drive, just has not every OS has a "/home" directory.
This rule checks for hardcoded, absolute paths in Files and all types of input and output streams.
Using wildcards in imports may look cleaner as it reduces the number of lines in the import section and simplifies the code. On the other hand, it makes the code harder to maintain:
It reduces code readability as developers will have a hard time knowing where names come from.
It could lead to conflicts between names defined locally and the ones imported.
It could later raise conflicts on dependency upgrade or Java version migration, as a wildcard import that works today might be broken tomorrow.
That is why it is better to import only the specific classes or modules you need.
Java 21 introduces the new method Math.clamp(value, min, max) that fits a value within a specified interval. Before Java 21, this behavior required explicit calls to the Math.min and Math.max methods, as in Math.min(max, Math.max(value, min)).
If min > max, Math.clamp throws an IllegalArgumentException, indicating an invalid interval. This can occur if the min and max arguments are mistakenly reversed.
Note that Math.clamp is not a general substitute for Math.min or Math.max, but for the combination of both. If value is the same as min or max, using Math.clamp is unnecessary and Math.min or Math.max should be used instead.
@Autowired is an annotation in the Spring Framework for automatic dependency injection. It tells Spring to automatically provide the required dependencies (such as other beans or components) to a class’s fields, methods, or constructors, allowing for easier and more flexible management of dependencies in a Spring application. In other words, it’s a way to wire up and inject dependencies into Spring components automatically, reducing the need for manual configuration and enhancing modularity and maintainability.
In any bean class, only one constructor is permitted to declare @Autowired with the required attribute set to true. This signifies the constructor to be automatically wired when used as a Spring bean. Consequently, when the required attribute remains at its default value (true), only a singular constructor can bear the @Autowired annotation. In cases where multiple constructors have this annotation, they must all specify required=false to be eligible as candidates for auto-wiring.
A Single Abstract Method (SAM) interface is a Java interface containing only one method. The Java API is full of SAM interfaces, such as \`java.lang.Runnable, java.awt.event.ActionListener, java.util.Comparator and java.util.concurrent.Callable. SAM interfaces have a special place in Java 8 because they can be implemented using Lambda expressions or Method references.
Using @FunctionalInterface forces a compile break when an additional, non-overriding abstract method is added to a SAM, which would break the use of Lambda implementations.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8\`.
Use of File.deleteOnExit() is not recommended for the following reasons:
The deletion occurs only in the case of a normal JVM shutdown but not when the JVM crashes or is killed.
For each file handler, the memory associated with the handler is released only at the end of the process.
When @Autowired is used, dependencies need to be resolved when the class is instantiated, which may cause early initialization of beans or lead the context to look in places it shouldn’t to find the bean. To avoid this tricky issue and optimize the way the context loads, dependencies should be requested as late as possible. That means using parameter injection instead of field injection for dependencies that are only used in a single @Bean method.
The right-hand side of a lambda expression can be written in two ways:
Expression notation: the right-hand side is as an expression, such as in (a, b) → a + b
Block notation: the right-hand side is a conventional function body with a code block and an optional return statement, such as in (a, b) → \{return a + b;}
By convention, expression notation is preferred over block notation. Block notation must be used when the function implementation requires more than one statement. However, when the code block consists of only one statement (which may or may not be a return statement), it can be rewritten using expression notation.
This convention exists because expression notation has a cleaner, more concise, functional programming style and is regarded as more readable.
Assertions comparing an object to itself are more likely to be bugs due to developer’s carelessness.
This rule raises an issue when the actual expression matches the expected expression.
Declaring multiple variables on one line is difficult to read.
The Java 8 version of \`HashMap handles key clashes by storing nodes in a binary tree when more than 11 keys clash with each other, and that tree needs to know the relative order of the keys. If you don’t provide a compareTo method, System.identityHashCode() will be used as the fallback, and that typically returns a value based on the object’s memory location, resulting in a performance degradation to O(n) where n is the number of objects at that map location.
Therefore, it’s considered a best practice to implement compareTo in classes that are used as HashMap keys.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8\`.
The use of a StringBuilder or StringBuffer is supposed to make String assembly more efficient than plain concatenation. So don’t ruin the effect by concatenating the arguments to append.
Using \`Integer.toHexString is a common mistake when converting sequences of bytes into hexadecimal string representations. The problem is that the method trims leading zeroes, which can lead to wrong conversions. For instance a two bytes value of 0x4508 would be converted into 45 and 8 which once concatenated would give 0x458.
This is particularly damaging when converting hash-codes and could lead to a security vulnerability.
This rule raises an issue when Integer.toHexString\` is used in any kind of string concatenations.
JUnit rules are predefined classes that extend the behavior of JUnit tests, allowing to add new functionalities, such as managing resources, modifying test behavior, and handling exceptions.
Unused JUnit rules can lead to confusion when reading the test code, making tests harder to understand and maintain. Having unused rules can also slow down the test suite, as JUnit has to process the rules even though they are not being used. Some TestRule classes have the desired effect without being directly referenced by a test, while others do not. There’s no reason to leave them cluttering the file if they’re not in use.
The rule raises an issue when in a Test class, there is no method referencing a declared TestRule of the following types:
TemporaryFolder and TestName in JUnit
TempDir and TestInfo in JUnit 5
According to the Java Language Specification:
It is permitted, but discouraged as a matter of style, to redundantly specify the
public and/or abstractmodifier for a method declared in an interface.
The classes in the sun.\* packages are not part of the official Java API and are not intended for public use. They are internal implementation details specific to the Oracle JDK (Java Development Kit). Therefore, their availability, behavior, or compatibility is not guaranteed across different Java implementations or versions.
Since these classes are not part of the official Java API, they usually lack proper documentation and support. Finding comprehensive and up-to-date information about their usage, functionality, and potential limitations can be challenging. This lack of documentation can make it difficult to understand how to use these classes correctly.
Classes in the sun.\* packages are often platform-dependent and can vary between different operating systems or Java Virtual Machine (JVM) implementations. Relying on these classes may lead to code that works on one platform but fails on others, limiting your code’s portability and cross-platform compatibility.
The \`java.util.regex.Pattern.compile() methods have a significant performance cost, and therefore should be used sensibly.
Moreover they are the only mechanism available to create instances of the Pattern class, which are necessary to do any pattern matching using regular expressions. Unfortunately that can be hidden behind convenience methods like String.matches() or String.split().
It is therefore somewhat easy to inadvertently repeatedly compile the same regular expression at great performance cost with no valid reason.
This rule raises an issue when:
A Pattern is compiled from a String literal or constant and is not stored in a static final reference.
String.matches, String.split, String.replaceAll or String.replaceFirst are invoked with a String literal or constant. In which case the code should be refactored to use a java.util.regex.Pattern\` while respecting the previous rule.
Java packages serve two purposes:
Structure — Packages give a structure to the set of classes of your project. It is a bad practice to put all classes flat into the source directory of a project without a package structure. A structure helps to mentally break down a project into smaller parts, simplifying readers' understanding of how components are connected and how they interact.
Avoiding name clashes — a class part of the default package if no explicit package name is specified. This can easily cause name collisions when other projects define a class of the same name.
When no package is explicitly specified for the classes in your project, this makes the project harder to understand and may cause name collisions with other projects. Also, classes located in the default package not be accessed from classes within named packages since Java 1.4.
A for loop is a type of loop construct that allows a block of code to be executed repeatedly for a fixed number of times. The for loop is typically used when the number of iterations is known in advance and consists of three parts:
The initialization statement is executed once at the beginning of the loop. It is used to initialize the loop counter or any other variables that may be used in the loop.
The loop condition is evaluated at the beginning of each iteration, and if it is true, the code inside the loop is executed.
The update statement is executed at the end of each iteration and is used to update the loop counter or any other variables that may be used in the loop.
When you call isEmpty(), it clearly communicates the code’s intention, which is to check if the collection is empty. Using \`size()
Servlets are components in Java web development, responsible for processing HTTP requests and generating responses. In this context, exceptions are used to handle and manage unexpected errors or exceptional conditions that may occur during the execution of a servlet.
Catching exceptions within the servlet allows us to convert them into meaningful, user-friendly messages. Otherwise, failing to catch exceptions will propagate them to the servlet container, where the default error-handling mechanism may impact the overall security and stability of the server.
Possible security problems are:
Vulnerability to denial-of-service attacks: Not caught exceptions can leave the servlet container in an unstable state, which can exhaust the available resources and make the system unavailable in the worst cases.
Exposure of sensitive information: Exceptions handled by the servlet container, by default, expose detailed error messages or debugging information to the user, which may contain sensitive data such as stack traces, database connection, or system configuration.
Unfortunately, servlet method signatures do not force developers to handle IOException and ServletException:
The purpose of Java packages is to give structure to your project. A structure helps to mentally break down a project into smaller parts, simplifying readers' understanding of how components are connected and how they interact.
By convention, the source files' directory structure should replicate the project’s package structure. This is for the following reasons:
The mapping between the package name and the location of the source file of a class is straightforward. That is, the path to the source file is easier to find for a given fully qualified class name.
If two different structures are applied to the same project - one to the packages but another to the source file directories - this confuses developers while not providing any benefit.
The directory structure of the class files generated by the compiler will match the package structure, no matter the source file’s directory. It would not make sense to have one directory structure for the generated class files but a different one for the associated source files.
Similarly, a source directory should not have the character . in its name, as this would make it impossible to match the directory to the package structure.
The Spring Framework provides several specializations of the generic @Component stereotype annotation which better express the programmer’s intent. Using them should be preferred.
Using compound operators as well as increments and decrements (and toggling, in the case of booleans) on primitive fields are not atomic operations. That is, they don’t happen in a single step. For instance, when a volatile primitive field is incremented or decremented you run the risk of data loss if threads interleave in the steps of the update. Instead, use a guaranteed-atomic class such as AtomicInteger, or synchronize the access.
\`Throwable is the superclass of all errors and exceptions in Java. Error is the superclass of all errors, which are not meant to be caught by applications.
Catching either Throwable or Error will also catch OutOfMemoryError and InternalError\`, from which an application should not attempt to recover.
A org.assertj.core.configuration.Configuration will be effective only once you call Configuration.apply() or Configuration.applyAndDisplay().
This rule raises an issue when configurations are set without the appropriate call to apply them.
When a class has all final fields, the compiler ensures that the object’s state remains constant. It also enforces a clear design intent of immutability, making the class easier to reason about and use correctly.
Exceptions are meant to represent the application’s state at the point at which an error occurred. Making all fields in an Exception class final ensures that these class fields do not change after initialization.
In the Java object lifecycle, the finalize method for an instance is called after the garbage collector has determined that the instance can be removed from the object heap. Therefore, it is unnecessary to implement a finalizer to set instance fields explicitly to null to tell the garbage collector that the instance no longer needs them.
In the worst case, implementing finalize is even counterproductive because it might accidentally create new references from other (living) objects on the heap to the collectible instance, thus, reviving it.
Important note about finalizers:
There are no guarantees when the Java Runtime will call the finalize method or whether it will be called at all.
Using finalizers is, therefore, a bad practice. They should never be used to free resources, such as closing streams, freeing locks, or freeing native system resources. Consider other freeing mechanisms instead, such as an explicit close, unlock, or free method in your class.
The ZonedDateTime is an immutable representation of a date-time with a time-zone, introduced in Java 8. This class stores all date and time fields, to a precision of nanoseconds, and a time zone, with a zone offset used to handle ambiguous local date times.
Date truncation to a specific time unit means setting the values up to the specific time unit to zero while keeping the values of the larger time units unchanged.
The ZonedDateTime class provides a truncatedTo method that allows truncating the date in a significantly faster way than the DateUtils class from Commons Lang.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8.
Passing a collection as an argument to the collection’s own method is either an error - some other argument was intended - or simply nonsensical code.
Further, because some methods require that the argument remain unmodified during the execution, passing a collection to itself can result in undefined behavior.
Developers may want to add some logic to handle deserialized objects before they are returned to the caller. This can be achieved by implementing the readResolve method.
Non-final classes implementing readResolve should not set its visibility to private as this would make it unavailable to child classes. Instead, mark readResolve as protected, allowing it to be inherited.
Generating random floating point values to cast them into integers is inefficient. A random bounded integer value can be generated with a single proper method call. Use nextInt to make the code more efficient and the intent clearer.
Concurrent maps are used for thread-safety, but the use of such maps alone does not ensure thread-safety; they must also be used in a thread-safe manner. Specifically, retrieving a key’s value from a map, and then using \`put to add a map element if the value is null is not performed in an atomic manner. Here’s what can happen
Thread1 cmap.get("key") => null
Thread2 cmap.get("key") => null
Thread1 cmap.put("key", new Value())
Thread2 cmap.put("key", new Value())
Note that this example is written as though the threads take turns performing operations, but that’s not necessarily the case.
Instead of put, putIfAbsent\` should be used.
Dynamically loaded classes could contain malicious code executed by a static class initializer. I.E. you wouldn’t even have to instantiate or explicitly invoke methods on such classes to be vulnerable to an attack.
This rule raises an issue for each use of dynamic class loading.
For arrays of objects, Arrays.asList(T ... a).stream() and Arrays.stream(array) are basically equivalent in terms of performance. However, for arrays of primitives, using Arrays.asList will force the construction of a list of boxed types, and then use that list as a stream. On the other hand, Arrays.stream uses the appropriate primitive stream type (IntStream, LongStream, DoubleStream) when applicable, with much better performance.
If a string fits on a single line, without concatenation and escaped newlines, you should probably continue to use a string literal.
You cannot assume that any given stream reading call will fill the \`byte\[] passed in to the method. Instead, you must check the value returned by the read method to see how many bytes were read. Fail to do so, and you introduce bug that is both harmful and difficult to reproduce.
Similarly, you cannot assume that InputStream.skip will actually skip the requested number of bytes, but must check the value returned from the method.
This rule raises an issue when an InputStream.read method that accepts a byte\[] is called, but the return value is not checked, and when the return value of InputStream.skip is not checked. The rule also applies to InputStream\` child classes.
Connections, streams, files, and other classes that implement the Closeable interface or its super-interface, AutoCloseable, needs to be closed after use. Further, that close call must be made in a finally block otherwise an exception could keep the call from being made. Preferably, when class implements AutoCloseable, resource should be created using "try-with-resources" pattern and will be closed automatically.
Failure to properly close resources will result in a resource leak which could bring first the application and then perhaps the box the application is on to their knees.
This rule involves the use of Math.abs and negation on numbers that could be MIN\_VALUE. It is a problem because it can lead to incorrect results and unexpected behavior in the program.
When Math.abs and negation are used on numbers that could be MIN\_VALUE, the result can be incorrect due to integer overflow. Common methods that can return a MIN\_VALUE and raise an issue when used together with Math.abs are:
Random.nextInt() and Random.nextLong()
hashCode()
compareTo()
Alternatively, the absExact() method throws an ArithmeticException for MIN\_VALUE.
By definition, primitive types are not Objects and so they can’t be \`null. Adding @CheckForNull or @Nullable on primitive types adds confusion and is useless.
This rule raises an issue when @CheckForNull or @Nullable\` is set on a method returning a primitive type: byte, short, int, long, float, double, boolean, char.
In Java, the Object.equals() method is used for object comparison, and it is typically overridden in classes to provide a custom equality check based on your criteria for equality.
The default implementation of equals() provided by the Object class compares the memory references of the two objects, that means it checks if the objects are actually the same instance in memory.
The "equals" as a method name should be used exclusively to override Object.equals(Object) to prevent confusion.
It is important to note that when you override equals(), you should also override the hashCode() method to maintain the contract between equals() and hashCode().
According to the documentation,
A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization…
For example (credit to Brian Goetz), imagine Foo is a value-based class:
Foo\[] arr = new Foo\[2];
arr\[0] = new Foo(0);
arr\[1] = new Foo(0);
Serialization promises that on deserialization of arr, elements 0 and 1 will not be aliased. Similarly, in:
Foo\[] arr = new Foo\[2];
arr\[0] = new Foo(0);
arr\[1] = arr\[0];
Serialization promises that on deserialization of \`arr, elements 0 and 1 will be aliased.
While these promises are coincidentally fulfilled in current implementations of Java, that is not guaranteed in the future, particularly when true value types are introduced in the language.
This rule raises an issue when a Serializable class defines a non-transient, non-static field field whose type is a known serializable value-based class. Known serializable value-based classes are: all the classes in the java.time package except Clock; the date classes for alternate calendars: HijrahDate, JapaneseDate, MinguoDate, ThaiBuddhistDate\`.
"Boxing" is the process of putting a primitive value into a primitive-wrapper object. When that’s done purely to use the wrapper class' toString method, it’s a waste of memory and cycles because those methods are static, and can therefore be used without a class instance. Similarly, using the static method valueOf in the primitive-wrapper classes with a non-String argument should be avoided.
The \`Class.isInstance method is the dynamic equivalent of the instanceof operator. According to the JavaDoc, isInstance
returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); it returns false otherwise
Thus, calling isInstance with a class argument is likely a mistake, since any random Class will only be "an instance of the represented class" when the left-hand side of the call is Class.class itself. To test for a class/sub-class relationship, use isAssignableFrom\` instead.
The String class has a toString method because Object itself does. I.e. it couldn’t not have the method. But having the method doesn’t mean it should be used. In fact doing so is worse than pointless since it returns the String itself.
Singletons that aren’t actually singletons become problems instead. To make sure a singleton isn’t instantiable, make sure all constructors are \`private. If the singleton doesn’t have any constructors then add a private no-args constructor to override the default constructor.
This rule raises an issue when a class that holds a public static final instance of itself has non-private\` constructors or no constructor.
A key facet of the \`equals contract is that if a.equals(b) then b.equals(a), i.e. that the relationship is symmetric.
Using instanceof breaks the contract when there are subclasses, because while the child is an instanceof the parent, the parent is not an instanceof the child. For instance, assume that Raspberry extends Fruit and adds some fields (requiring a new implementation of equals):
Fruit fruit = new Fruit();
Raspberry raspberry = new Raspberry();
if (raspberry instanceof Fruit) \{ ... } // true
if (fruit instanceof Raspberry) \{ ... } // false
If similar instanceof checks were used in the classes' equals methods, the symmetry principle would be broken:
raspberry.equals(fruit); // false
fruit.equals(raspberry); //true
Additionally, non final classes shouldn’t use a hardcoded class name in the equals method because doing so breaks the method for subclasses. Instead, make the comparison dynamic.
Further, comparing to an unrelated class type breaks the contract for that unrelated type, because while thisClass.equals(unrelatedClass) can return true, unrelatedClass.equals(thisClass)\` will not.
Map computeIfAbsent and computeIfPresent methods are convenient to avoid the cumbersome process to check if a key exists or not, followed by the addition of the entry. However, when the function used to compute the value returns \`null, the entry key->null will not be added to the Map. Furthermore, in the case of computeIfPresent, if the key is present the entry will be removed. These methods should therefore not be used to conditionally add an entry with a null value. The traditional way should be used instead.
This rule raises an issue when computeIfAbsent or computeIfPresent\` is used with a lambda always returning null.
Before Java 8, the only way to partially support closures in Java was by using anonymous inner classes. Java 8 introduced lambdas, which are significantly more readable and should be used instead.
This rule is automatically disabled when the project’s sonar.java.source is lower than 8, as lambda expressions were introduced in Java 8.
If the region is not specified when creating a new AwsClient with an AwsClientBuilder, the AWS SDK will execute some logic to identify the endpoint automatically.
While it will probably identify the correct one, this extra logic will slow down startup time, already known to be a hotspot.
You should therefore always define the logic to set the region yourself. This is typically done by retrieving the region from the Lambda provided AWS\_REGION environment variable.
This will make the code more explicit and spare initialization time.
This rule reports an issue when the region is not set when creating an AwsClient.
Because Object implements hashCode, any Java class can be put into a hash structure. However, classes that define equals(Object) but not hashCode() aren’t truly hash-able because instances that are equivalent according to the equals method can return different hashes.
Java serialization is the conversion from objects to byte streams for storage or transmission. And later, java deserialization is the reverse conversion, it reconstructs objects from byte streams.
To make a java class serializable, this class should implement the java.io.Serializable interface directly or through its inheritance.
Failure to specify a locale when calling the methods \`toLowerCase(), toUpperCase() or format() on String objects means the system default encoding will be used, possibly creating problems with international characters or number representations. For instance with the Turkish language, when converting the small letter 'i' to upper case, the result is capital letter 'I' with a dot over it.
Case conversion without a locale may work fine in its "home" environment, but break in ways that are extremely difficult to diagnose for customers who use different encodings. Such bugs can be nearly, if not completely, impossible to reproduce when it’s time to fix them. For locale-sensitive strings, the correct locale should always be used, but Locale.ROOT\` can be used for case-insensitive ones.
If all the keys in a Map are values from a single enum, it is recommended to use an EnumMap as the specific implementation. An EnumMap, which has the advantage of knowing all possible keys in advance, is more efficient compared to other implementations, as it can use a simple array as its underlying data structure.
The implementation of certain \`ResultSet methods is optional for result sets of type TYPE\_FORWARD\_ONLY. Even if your current JDBC driver does implement those methods, there’s no guarantee you won’t change drivers in the future.
This rule looks for invocations of the following methods on TYPE\_FORWARD\_ONLY ResultSets:
isBeforeFirst
isAfterLast
isFirst
getRow\`
Return of boolean literal statements wrapped into \`if-then-else ones should be simplified.
Similarly, method invocations wrapped into if-then-else\` differing only from boolean literals should be simplified into a single invocation.
While not mandatory, using the @Override annotation on compliant methods improves readability by making it explicit that methods are overriden.
A compliant method either overrides a parent method or implements an interface or abstract method.
Since an int is a 32-bit variable, shifting by more than +/-31 is confusing at best and an error at worst. When the runtime shifts 32-bit integers, it uses the lowest 5 bits of the shift count operand. In other words, shifting an int by 32 is the same as shifting it by 0, and shifting it by 33 is the same as shifting it by 1.
Similarly, when shifting 64-bit integers, the runtime uses the lowest 6 bits of the shift count operand and shifting long by 64 is the same as shifting it by 0, and shifting it by 65 is the same as shifting it by 1.
Whenever a virtual thread is started, the JVM will mount it on an OS thread. As soon as the virtual thread runs into a blocking operation like an HTTP request or a filesystem read/write operation, the JVM will detect this and unmount the virtual thread. This allows another virtual thread to take over the OS thread and continue its execution.
This is why virtual threads should be preferred to platform threads for tasks that involve blocking operations. By default, a Java thread is a platform thread. To use a virtual thread it must be started either with Thread.startVirtualThread(Runnable) or Thread.ofVirtual().start(Runnable).
This rule raises an issue when a platform thread is created with a task that includes heavy blocking operations.
There is no reason to concatenate literal strings. Doing so is an exercise is reducing code readability. Instead, the strings should be combined. Similarly, literal strings should not be appended to a StringBuffer or StringBuilder sequentially, but combined into one call.
In Spring, singleton beans and their dependencies are initialized when the application context is created.
If a Singleton bean depends on a bean with a shorter-lived scope (like Request or Session beans), it retains the same instance of that bean, even when new instances are created for each Request or Session. This mismatch can cause unexpected behavior and bugs, as the Singleton bean doesn’t interact correctly with the new instances of the shorter-lived bean.
This rule raises an issue when non-singleton beans are injected into a singleton bean.
Java 21 introduces the new Sequenced Collections API, which is applicable to all collections with a defined sequence on their elements, such as LinkedList, TreeSet, and others (see JEP 431). For projects using Java 21 and onwards, this API should be utilized instead of workaround implementations that were necessary before Java 21.
This rule reports when a collection is iterated in reverse through explicit implementation or workarounds, instead of using the reversed view of the collection.
The purpose of checked exceptions is to ensure that errors will be dealt with, either by propagating them or by handling them, but some believe that checked exceptions negatively impact the readability of source code, by spreading this error handling/propagation logic everywhere.
This rule verifies that no method throws a new checked exception.
A class that implements java.io.Externalizable is a class that provides a way to customize the serialization and deserialization, allowing greater control over how the object’s state is written or read.
The first step of the deserialization process is to call the class' no-argument constructor before the readExternal(ObjectInput in) method.
An implicit default no-argument constructor exists on a class when no constructor is explicitly defined within the class. But this implicit constructor does not exist when any constructor is explicitly defined, and in this case, we should always ensure that one of the constructors has no-argument.
It is an issue if the implicit or explicit no-argument constructor is missing or not public, because the deserialization will fail and throw an InvalidClassException: no valid constructor..
Deprecated method should be avoided, rather than overridden. Deprecation is a warning that the method has been superseded, and will eventually be removed. The deprecation period allows you to make a smooth transition away from the aging, soon-to-be-retired technology.
In Java 16, the feature "Pattern matching for instanceof" is finalized and can be used in production. Previously developers needed to do 3 operations in order to do this: check the variable type, cast it and assign the casted value to the new variable. This approach is quite verbose and can be replaced with pattern matching for \`instanceof, doing these 3 actions (check, cast and assign) in one expression.
This rule raises an issue when an instanceof\` check followed by a cast and an assignment could be replaced by pattern matching.
Making a \`public constant just final as opposed to static final leads to duplicating its value for every instance of the class, uselessly increasing the amount of memory required to execute the application.
Further, when a non-public, final field isn’t also static, it implies that different instances can have different values. However, initializing a non-static final field in its declaration forces every instance to have the same value. So such fields should either be made static\` or initialized in the constructor.
Strings are immutable objects, so concatenation doesn’t simply add the new String to the end of the existing string. Instead, in each loop iteration, the first String is converted to an intermediate object type, the second string is appended, and then the intermediate object is converted back to a String. Further, performance of these intermediate operations degrades as the String gets longer. Therefore, the use of StringBuilder is preferred.
Using the standard getClassLoader() may not return the right class loader in a JEE context. Instead, go through the currentThread.
A generic type is a generic class or interface that is parameterized over types. For example, java.util.List has one type parameter: the type of its elements.
When generic types are used raw (without type parameters), the compiler is not able to do generic type checking. For this reason, it is sometimes necessary to cast objects and defer type-checking to runtime.
In a multithreaded environment, a thread may need to wait for a particular condition to become true. One way of pausing execution in Java is Thread.sleep(…).
If a thread that holds a lock calls Thread.sleep(…), no other thread can acquire said lock. This can lead to performance and scalability issues, in the worst case leading to deadlocks.
Creating a new Random object each time a random value is needed is inefficient and may produce numbers that are not random, depending on the JDK. For better efficiency and randomness, create a single Random, store it, and reuse it.
The Random() constructor tries to set the seed with a distinct value every time. However, there is no guarantee that the seed will be randomly or uniformly distributed. Some JDK will use the current time as seed, making the generated numbers not random.
This rule finds cases where a new Random is created each time a method is invoked.
As mentioned in JUnit5 documentation, it is possible to integrate JUnit4 with JUnit5:
JUnit provides a gentle migration path via a JUnit Vintage test engine which allows existing tests based on JUnit 3 and JUnit 4 to be executed using the JUnit Platform infrastructure. Since all classes and annotations specific to JUnit Jupiter reside under a new org.junit.jupiter base package, having both JUnit 4 and JUnit Jupiter in the classpath does not lead to any conflicts.
However, maintaining both systems is a temporary solution. This rule flags all the annotations from JUnit4 which would need to be migrated to JUnit5, hence helping migration of a project.
Here is the list of JUnit4 annotations tracked by the rule, with their corresponding annotations in JUnit5:
| JUnit4 | JUnit5 |
|---|---|
\`org.junit.Test |
org.junit.jupiter.api.Test |
org.junit.Before |
org.junit.jupiter.api.BeforeEach |
org.junit.After |
org.junit.jupiter.api.AfterEach |
org.junit.BeforeClass |
org.junit.jupiter.api.BeforeAll |
org.junit.AfterClass |
org.junit.jupiter.api.AfterAll |
org.junit.Ignore |
org.junit.jupiter.api.Disabled |
Note that the following annotations might requires some rework of the tests to have JUnit5 equivalent behavior. A simple replacement of the annotation won’t work immediately:
| JUnit4 | JUnit5 |
|---|---|
org.junit.experimental.categories.Category |
org.junit.jupiter.api.Tag |
org.junit.Rule |
org.junit.jupiter.api.extension.ExtendWith |
org.junit.ClassRule |
org.junit.jupiter.api.extension.RegisterExtension |
org.junit.runner.RunWith |
org.junit.jupiter.api.extension.ExtendWith\` |
Field injection seems like a tidy way to get your classes what they need to do their jobs, but it’s really a \`NullPointerException waiting to happen unless all your class constructors are private. That’s because any class instances that are constructed by callers, rather than instantiated by a Dependency Injection framework compliant with the JSR-330 (Spring, Guice, …), won’t have the ability to perform the field injection.
Instead @Inject should be moved to the constructor and the fields required as constructor parameters.
This rule raises an issue when classes with non-private\` constructors (including the default constructor) use field injection.
Either use only spaces or only tabs for the indentation of a text block. Mixing white space will lead to a result with irregular indentation.
With Java 8’s "default method" feature, any abstract class without direct or inherited field should be converted into an interface. However, this change may not be appropriate in libraries or other applications where the class is intended to be used as an API.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8.
Rather than creating a boxed primitive from a String to extract the primitive value, use the relevant parse method instead. Using parse makes the code more efficient and the intent of the developer clearer.
In general, altering or bypassing the accessibility of classes, methods, or fields violates the encapsulation principle and could lead to runtime errors. For records the case is even trickier: you cannot change the visibility of records’s fields and trying to update the existing value will lead to IllegalAccessException at runtime.
This rule raises an issue when reflection is used to change the visibility of a record’s field, and when it is used to directly update a record’s field value.
When a class overrides Object.equals, this indicates that the class not just considers object identity as equal (the default implementation of Object.equals) but implements another logic for what is considered equal in the context of this class. Usually (but not necessarily), the semantics of equals in this case is that two objects are equal when their state is equal field by field.
Because of this, adding new fields to a subclass of a class that overrides Object.equals but not updating the implementation of equals in the subclass is most likely an error.
Due to the similar name with the methods Object.toString, Object.hashCode and Object.equals, there is a significant likelihood that a developer intended to override one of these methods but made a spelling error.
Even if no such error exists and the naming was done on purpose, these method names can be misleading. Readers might not notice the difference, or if they do, they may falsely assume that the developer made a mistake.
Dependency injection frameworks such as Spring support dependency injection by using annotations such as @Inject and @Autowired. These annotations can be used to inject beans via constructor, setter, and field injection.
Generally speaking, field injection is discouraged. It allows the creation of objects in an invalid state and makes testing more difficult. The dependencies are not explicit when instantiating a class that uses field injection.
In addition, field injection is not compatible with final fields. Keeping dependencies immutable where possible makes the code easier to understand, easing development and maintenance.
Finally, because values are injected into fields after the object has been constructed, they cannot be used to initialize other non-injected fields inline.
This rule raises an issue when the @Autowired or @Inject annotations are used on a field.
JUnit5 is more tolerant regarding the visibility of test classes and methods than JUnit4, which required everything to be public. Test classes and methods can have any visibility except private. It is however recommended to use the default package visibility to improve readability.
Test classes, test methods, and lifecycle methods are not required to be public, but they must not be private.
It is generally recommended to omit the public modifier for test classes, test methods, and lifecycle methods unless there is a technical reason for doing so – for example, when a test class is extended by a test class in another package. Another technical reason for making classes and methods public is to simplify testing on the module path when using the Java Module System.
A method annotated with Spring’s @Async or @Transactional annotations will not work as expected if invoked directly from within its class.
This is because Spring generates a proxy class with wrapper code to manage the method’s asynchronicity (@Async) or to handle the transaction (@Transactional). However, when called using this, the proxy instance is bypassed, and the method is invoked directly without the required wrapper code.
An infinite loop will never end while the program runs, meaning you have to kill the program to get out of the loop. Every loop should have an end condition, whether by meeting the loop’s termination condition or via a break statement.
In Spring Framework, the @Qualifier annotation is typically used to disambiguate between multiple beans of the same type when auto-wiring dependencies. It is not necessary to use @Qualifier when defining a bean using the @Bean annotation because the bean’s name can be explicitly specified using the name attribute or derived from the method name. Using @Qualifier on @Bean methods can lead to confusion and redundancy. Beans should be named appropriately using either the name attribute of the @Bean annotation or the method name itself.
Maps use hashes of the keys to select a bucket to store data in. Objects that hash to the same value will be added to the same bucket.
When the hashing function has a poor distribution, buckets can grow to very large sizes. This may negatively affect lookup performance, as, by default, matching a key within a bucket has linear complexity.
In addition, as the default hashCode function can be selected at runtime, performance expectations cannot be maintained.
Implementing Comparable mitigates the performance issue for objects that hash to the same value.
The IllegalMonitorStateException is an exception that occurs when a thread tries to perform an operation on an object’s monitor that it does not own. This exception is typically thrown when a method like wait(), notify(), or notifyAll() is called outside a synchronized block or method.
IllegalMonitorStateException is specifically designed to be an unchecked exception to point out a programming mistake. This exception serves as a reminder for developers to rectify their code by correctly acquiring and releasing locks using synchronized blocks or methods. It also emphasizes the importance of calling monitor-related methods on the appropriate objects to ensure proper synchronization.
Catching and handling this exception can mask underlying synchronization issues and lead to unpredictable behavior.
Tests should always:
Make sure that production code behaves as expected, including edge cases.
Be easy to debug, i.e. understandable and reproducible.
Using random values in tests will not necessarily check edge cases, and it will make test logs a lot harder to read. It is better to use easily readable hardcoded values. If this makes your code bigger you can use helper functions.
There is one valid use case for random data in tests: when testing every value would make tests impractically slow. In this case the best you can do is use random to test every value on the long run. You should however make sure that random values are logged so that you can reproduce failures. Some libraries exist to make all this easier. You can for example use property-based testing libraries such as jqwik.
This rule raises an issue when new Random() or UUID.randomUUID() are called in test code.
Double-checked locking is the practice of checking a lazy-initialized object’s state both before and after a synchronized block is entered to determine whether to initialize the object. In early JVM versions, synchronizing entire methods was not performant, which sometimes caused this practice to be used in its place.
Apart from float and int types, this practice does not work reliably in a platform-independent manner without additional synchronization of mutable instances. Using double-checked locking for the lazy initialization of any other type of primitive or mutable object risks a second thread using an uninitialized or partially initialized member while the first thread is still creating it. The results can be unexpected, potentially even causing the application to crash.
To check the type of an object there are at least two options:
The simplest and shortest one with help of the \`instanceof operator
The cumbersome and error-prone one with help of the Class.isAssignableFrom(...)\` method
When a cycle exists between classes during their static initialization, the results can be unpredictable because they depend on which class was initialized first.
\`transient fields are ignored by Java’s automatic serizalization mechanisms, which means that when a object is deserialized, those fields will be set to their default values.
transient fields that are referenced in multiple places in a class seem to play a significant role in that class. Allowing such significant fields to be left in a default state after deserialization may not be the best course, so they should probably be set in either a readObject() or readResolve()\` method.
A synchronized method is a method marked with the synchronized keyword, meaning it can only be accessed by one thread at a time. If multiple threads try to access the synchronized method simultaneously, they will be blocked until the method is available.
Synchronized methods prevent race conditions and data inconsistencies in multi-threaded environments. Ensuring that only one thread can access a method at a time, prevents multiple threads from modifying the same data simultaneously, and causing conflicts.
When one part of a getter/setter pair is synchronized the other should be too. Failure to synchronize both sides may result in inconsistent behavior at runtime as callers access an inconsistent method state.
This rule raises an issue when either the method or the contents of one method in a getter/setter pair are synchronized, but the other is not.
In the past, it was required to load a JDBC driver before creating a \`java.sql.Connection. Nowadays, when using JDBC 4.0 drivers, this is no longer required and Class.forName() can be safely removed because JDBC 4.0 (JDK 6) drivers available in the classpath are automatically loaded.
This rule raises an issue when Class.forName() is used with one of the following values:
com.mysql.jdbc.Driver
oracle.jdbc.driver.OracleDriver
com.ibm.db2.jdbc.app.DB2Driver
com.ibm.db2.jdbc.net.DB2Driver
com.sybase.jdbc.SybDriver
com.sybase.jdbc2.jdbc.SybDriver
com.teradata.jdbc.TeraDriver
com.microsoft.sqlserver.jdbc.SQLServerDriver
org.postgresql.Driver
sun.jdbc.odbc.JdbcOdbcDriver
org.hsqldb.jdbc.JDBCDriver
org.h2.Driver
org.firebirdsql.jdbc.FBDriver
net.sourceforge.jtds.jdbc.Driver
com.ibm.db2.jcc.DB2Driver\`
The Spring framework comes with dedicated classes to help writing better and simpler unit tests. In particular, when testing applications built on top of Spring MVC, it is recommended to use Spring’s \`ModelAndViewAssert assertions class, instead of manually testing MVC’s properties.
This rule raises an issue when Spring’s ModelAndViewAssert\` assertions should be used instead of manual testing.
There is no reason to have a \`main method in a web application. It may have been useful for debugging during application development, but such a method should never make it into production. Having a main method in a web application opens a door to the application logic that an attacker may never be able to reach (but watch out if one does!), but it is a sloppy practice and indicates that other problems may be present.
This rule raises an issue when a main\` method is found in a servlet or an EJB.
By default, Hibernate session flushing is set to FlushMode.AUTO, and is called from Transaction.commit, Session.flush and before some queries are executed. Setting it to FlushMode.COMMIT, FlushMode.NEVER, or FlushMode.MANUAL could mean that parts of your application get stale data, so you should be sure of what you’re doing before you use any of these modes.
This rule raises an issue when flush mode is explicitly set to any of these modes.
While this can be useful, whenever we want to instantiate and start an unnamed virtual thread, there is a more convenient static method to do so: Thread.startVirtualThread(Runnable task)
This rule raises an issue every time the form Thread.ofVirtual().start(task); is found.
Since Java 9, \`@Deprecated has two additional arguments to the annotation:
since allows you to describe when the deprecation took place
forRemoval, indicates whether the deprecated element will be removed at some future date
In order to ease the maintainers work, it is recommended to always add one or both of these arguments.
This rule reports an issue when @Deprecated\` is used without any argument.
rm is security-sensitive. For example, their use has led in the past to the following vulnerability:
All classes extending org.apache.struts.action.Action are potentially remotely reachable. The ActionForm object provided as a parameter of the execute method is automatically instantiated and populated with the HTTP parameters. One should review the use of these parameters to be sure they are used safely.
The array brackets (\[]) for methods that return arrays may appear either immediately after the array type or after the list of parameters. Both styles will compile, but placing array brackets at the end of the method signature is deprecated, and retained in the language specification only for backward compatibility.
Additionally, placing the array brackets at the end is far less readable than keeping the brackets with the return type. Therefore, this style should be found only in legacy code, never in new code.
The hasNext method of an Iterator should only report on the state of the iterator, not change it. Making a change to an iterator in its hasNext method violates all expectations of what the method will do, and almost guarantees bad results when the iterator class is used.
xtract strings from an application source code or binary, passwords should not be hard-coded. This is particularly true for applications that are distributed or that are open-source.
In the past, it has led to the following vulnerabilities:
Passwords should be stored outside of the code in a configuration file, a database, or a password management service.
This rule flags instances of hard-coded passwords used in database and LDAP connections. It looks for hard-coded passwords in connection strings, and for variable names that match any of the patterns from the provided list.
Because Double Brace Initialization (DBI) creates an anonymous class with a reference to the instance of the owning object, its use can lead to memory leaks if the anonymous inner class is returned and held by other objects. Even when there’s no leak, DBI is so obscure that it’s bound to confuse most maintainers.
For collections, use Arrays.asList instead, or explicitly add each item directly to the collection.
In records, the default behavior of the \`equals() method is to check the equality by field values. This works well for primitive fields or fields, whose type overrides equals(), but this behavior doesn’t work as expected for array fields.
By default, array fields are compared by their reference, and overriding equals() is highly appreciated to achieve the deep equality check. The same strategy applies to hashCode() and toString() methods.
This rule reports an issue if a record class has an array field and is not overriding equals(), hashCode() or toString()\` methods.
According to Hibernate’s documentation:
Hibernate’s own connection pooling algorithm is, … quite rudimentary. It is intended to help you get started and is not intended for use in a production system, or even for performance testing. You should use a third party pool for best performance and stability.
This rule raises an issue when a hibernate.connection.pool\_size value is found in a hibernate.cfg.xml or hibernate.properties file.
Nested \`switch structures are difficult to understand because you can easily confuse the cases of an inner switch as belonging to an outer statement or expression. Therefore nested switch statements and expressions should be avoided.
Specifically, you should structure your code to avoid the need for nested switch statements or expressions, but if you cannot, then consider moving the inner switch\` to another method.
Invoking other Lambdas synchronously from a Lambda is a scalability anti-pattern. Lambdas have a maximum execution time before they timeout (15 minutes as of May 2021). Having to wait for another Lambda to finish its execution could lead to a timeout.
A better solution is to generate events that can be consumed asynchronously by other Lambdas.
Non-static initializers, also known as instance initializers, are blocks of code within a class that are executed when an instance of the class is created. They are executed when an object of the class is created just before the constructor is called. Non-static initializers are useful when you want to perform some common initialization logic for all objects of a class. They allow you to initialize instance variables in a concise and centralized manner, without having to repeat the same initialization code in each constructor.
While non-static initializers may have some limited use cases, they are rarely used and can be confusing for most developers because they only run when new class instances are created.
The counter of a for loop should be updated in the loop’s increment clause. The purpose of a for loop is to iterate over a range using a counter variable. It should not be used for other purposes, and alternative loops should be used in those cases.
If the counter is not updated, the loop will be infinite with a constant counter variable. If this is intentional, use a while or do while loop instead of a for loop.
If the counter variable is updated within the loop’s body, try to move it to the increment clause. If this is impossible due to certain conditions, replace the for loop with a while or do while loop.
Many resources in Java need be closed after they have been used. If they are not, the garbage collector cannot reclaim the resources' memory, and they are still considered to be in use by the operating system. Such resources are considered to be leaked, which can lead to performance issues.
Java 7 introduced the try-with-resources statement, which guarantees that the resource in question will be closed.
When a test fails due, for example, to infrastructure issues, you might want to ignore it temporarily. But without some kind of notation about why the test is being ignored, it may never be reactivated. Such tests are difficult to address without comprehensive knowledge of the project, and end up polluting their projects.
This rule raises an issue for each ignored test that does not have any comment about why it is being skipped.
For Junit4, this rule targets the @Ignore annotation.
For Junit5, this rule targets the @Disabled annotation.
Cases where assumeTrue(false) or assumeFalse(true) are used to skip tests are targeted as well.
JUnit5 is more tolerant regarding the visibilities of Test classes and methods than JUnit4, which required everything to be public. JUnit5 supports default package, public and protected visibility, even if it is recommended to use the default package visibility, which improves the readability of code.
But JUnit5 ignores without any warning:
private classes and private methods
static methods
methods returning a value without being a TestFactory
A test case without assertions ensures only that no exceptions are thrown. Beyond basic runnability, it ensures nothing about the behavior of the code under test.
This rule raises an exception when no assertions from any of the following known frameworks are found in a test:
AssertJ
Awaitility
EasyMock
Eclipse Vert.x
Fest 1.x and 2.x
Hamcrest
JMock
JMockit
JUnit
Mockito
Rest-assured 2.x, 3.x and 4.x
RxJava 1.x and 2.x
Selenide
Spring’s \`org.springframework.test.web.servlet.ResultActions.andExpect() and org.springframework.test.web.servlet.ResultActions.andExpectAll()
Truth Framework
WireMock
Furthermore, as new or custom assertion frameworks may be used, the rule can be parametrized to define specific methods that will also be considered as assertions. No issue will be raised when such methods are found in test cases. The parameter value should have the following format \
Example: com.company.CompareToTester#compare\*,com.company.CustomAssert#customAssertMethod,com.company.CheckVerifier#\
Non-static inner classes contain a reference to an instance of the outer class. Hence, serializing a non-static inner class will result in an attempt at serializing the outer class as well. If the outer class is not serializable, serialization will fail, resulting in a runtime error.
Making the inner class static (i.e., "nested") avoids this problem, as no reference to an instance of the outer class is required. Serializing the inner class can be done independently of the outer class. Hence, inner classes implementing Serializable should be static if the outer class does not implement Serializable.
Be aware of the semantic differences between an inner class and a nested one:
an inner class can only be instantiated within the context of an instance of the outer class.
a nested (static) class can be instantiated independently of the outer class.
The java.util.Collection type and its subtypes provide methods to access and modify collections such as Collection.remove(Object o) and Collection.contains(Object o). Some of these methods accept arguments of type java.lang.Object and will compare said argument with objects already in the collection.
If the actual type of the argument is unrelated to the type of object contained in the collection, these methods will always return false, null, or -1. This behavior is most likely unintended and can be indicative of a design issue.
This rule raises an issue when the type of the argument provided to one of the following methods is unrelated to the type used for the collection declaration:
Collection.remove(Object o)
Collection.removeAll(Collection\>)
Collection.contains(Object o)
List.indexOf(Object o)
List.lastIndexOf(Object o)
Map.containsKey(Object key)
Map.containsValue(Object value)
Map.get(Object key)
Map.getOrDefault(Object key, V defaultValue)
Map.remove(Object key)
Map.remove(Object key, Object value)
When implementing the \`Comparable\
This rule raises an issue when the parameter of the compareTo method of a class implementing Comparable\
The @Remote annotation indicates that an interface may be called from a remote client. Therefore the parameters and return types of methods in the interface must be Serializable.
Using \`return, break, throw, and so on from a finally block suppresses the propagation of any unhandled Throwable which was thrown in the try or catch block.
This rule raises an issue when a jump statement (break, continue, return, throw, and goto) would force control flow to leave a finally\` block.
If not annotated with \`@Nested, an inner class containing some tests will never be executed during tests execution. While you could still be able to manually run its tests in an IDE, it won’t be the case during the build. By contrast, a static nested class containing some tests should not be annotated with @Nested, JUnit5 will not share setup and state with an instance of its enclosing class.
This rule raises an issue on inner classes and static nested classes containing JUnit5 test methods which has a wrong usage of @Nested\` annotation.
Note: This rule does not check if the context in which JUnit 5 is running (e.g. Maven Surefire Plugin) is properly configured to execute static nested classes, it could not be the case using the default configuration.
Comparing a variable to multiple cases is a frequent operation. This can be done using a sequence of if-else statements. However, for many cases like enums or simple value comparisons, a switch statement is the better alternative. With Java 21, the switch statement has been significantly improved to support pattern matching and record pattern.
Using a switch statement instead of an if-else chain provides benefits like clearer code, certainty of covering all cases, and may even improve performance.
This rule raises an issue when an if-else chain should be replaced by a switch statement.
The Java Language Specification defines a set of rules called naming conventions that apply to Java programs. These conventions provide recommendations for naming packages, classes, methods, and variables.
By following shared naming conventions, teams can collaborate more efficiently.
This rule checks that static non-final field names match a provided regular expression.
Double.longBitsToDouble converts the bit pattern into its corresponding floating-point representation. The method expects a 64-bit long argument to interpret the bits as a double value correctly.
When the argument is a smaller data type, the cast to long may lead to a different value than expected due to the interpretation of the most significant bit, which, in turn, results in Double.longBitsToDouble returning an incorrect value.
"@EnableAutoConfiguration" is a convenient feature to configure the Spring Application Context by attempting to guess the beans that you are likely to need. The drawback is that it may load and configure beans the application will never use and therefore consume more CPU and RAM than really required. \`@EnableAutoConfiguration should be configured to exclude all the beans not required by the application. Alternatively, use the @Import annotation instead of @EnableAutoConfiguration, to explicitly import the useful AutoConfiguration classes.
This rule applies for @SpringBootApplication\` as well.
Overriding the \`Object.finalize() method must be done with caution to dispose some system resources.
Calling the super.finalize()\` at the end of this method implementation is highly recommended in case parent implementations must also dispose some system resources.
If a lock is acquired and released within a method, then it must be released along all execution paths of that method.
Failing to do so will expose the conditional locking logic to the method’s callers and hence be deadlock-prone.
Exposing HTTP endpoints is security-sensitive. It has led in the past to the following vulnerabilities:
HTTP endpoints are webservices' main entrypoint. Attackers will take advantage of any vulnerability by sending crafted inputs for headers (including cookies), body and URI. No input should be trusted and extreme care should be taken with all returned value (header, body and status code).
This rule flags code which creates HTTP endpoint. It guides security code reviews to security-sensitive code.
Overly complicated regular expressions are hard to read and to maintain and can easily cause hard-to-find bugs. If a regex is too complicated, you should consider replacing it or parts of it with regular code or splitting it apart into multiple patterns at least.
The complexity of a regular expression is determined as follows:
Each of the following operators increases the complexity by an amount equal to the current nesting level and also increases the current nesting level by one for its arguments:
\`| - when multiple | operators are used together, the subsequent ones only increase the complexity by 1
&& (inside character classes) - when multiple && operators are used together, the subsequent ones only increase the complexity by 1
Quantifiers (\*, +, ?, \{n,m}, \{n,} or \{n})
Non-capturing groups that set flags (such as (?i:some\_pattern) or (?i)some\_pattern\`)
Lookahead and lookbehind assertions
Additionally, each use of the following features increase the complexity by 1 regardless of nesting:
character classes
back references
If a regular expression is split among multiple variables, the complexity is calculated for each variable individually, not for the whole regular expression. If a regular expression is split over multiple lines, each line is treated individually if it is accompanied by a comment (either a Java comment or a comment within the regular expression), otherwise the regular expression is analyzed as a whole.
Jump statements such as return and continue let you change the default flow of program execution, but jump statements that direct the control flow to the original direction are just a waste of keystrokes.
Inappropriate casts are errors that will lead to bugs as the members are accessed. This includes casts from one unrelated type to another, as well as untested casts down an inheritance hierarchy.
Storing data locally is a common task for mobile applications. Such data includes preferences or authentication tokens for external services, among other things. There are many convenient solutions that allow storing data persistently, for example SQLiteDatabase, SharedPreferences, and Realm. By default these systems store the data unencrypted, thus an attacker with physical access to the device can read them out easily. Access to sensitive data can be harmful for the user of the application, for example when the device gets stolen.
Regular expressions have their own syntax that is understood by regular expression engines. Those engines will throw an exception at runtime if they are given a regular expression that does not conform to that syntax.
To avoid syntax errors, special characters should be escaped with backslashes when they are intended to be matched literally and references to capturing groups should use the correctly spelled name or number of the group.
Operating systems have global directories where any user has write access. Those folders are mostly used as temporary storage areas like \`/tmp in Linux based systems. An application manipulating files from these folders is exposed to race conditions on filenames: a malicious user can try to create a file with a predictable name before the application does. A successful attack can result in other files being accessed, modified, corrupted or deleted. This risk is even higher if the application runs with elevated permissions.
In the past, it has led to the following vulnerabilities:
This rule raises an issue whenever it detects a hard-coded path to a publicly writable directory like /tmp (see examples bellow). It also detects access to environment variables that point to publicly writable directories, e.g., TMP and TMPDIR.
/tmp
/var/tmp
/usr/tmp
/dev/shm
/dev/mqueue
/run/lock
/var/run/lock
/Library/Caches
/Users/Shared
/private/tmp
/private/var/tmp
\Windows\Temp
\Temp
\TMP\`
Shared naming conventions allow teams to collaborate efficiently. This rule raises an issue when a test class name does not match the provided regular expression.
WebViews can be used to display web content as part of a mobile application. A browser engine is used to render and display the content. Like a web application, a mobile application that uses WebViews can be vulnerable to Cross-Site Scripting if untrusted code is rendered.
If malicious JavaScript code in a WebView is executed this can leak the contents of sensitive files when access to local files is enabled.
Sub-patterns can be wrapped by parentheses to build a group. This enables to restrict alternations, back reference the group or apply quantifier to the sub-pattern.
If this group should not be part of the match result or if no reference to this group is required, a non-capturing group can be created by adding ?: behind the opening parenthesis.
However, if this non-capturing group does not have a quantifier, or does not wrap an alternation, then imaging this group is redundant.
Curly brace quantifiers in regular expressions can be used to have a more fine-grained control over how many times the character or the sub-expression preceeding them should occur. They can be used to match an expression exactly n times with \`\{n}, between n and m times with \{n,m}, or at least n times with \{n,}. In some cases, using such a quantifier is superfluous for the semantic of the regular expression, and it can be removed to improve readability. This rule raises an issue when one of the following quantifiers is encountered:
\{1,1} or \{1}: they match the expression exactly once. The same behavior can be achieved without the quantifier.
\{0,0} or \{0}\`: they match the expression zero times. The same behavior can be achieved by removing the expression.
Most of the regular expression engines use backtracking to try all possible execution paths of the regular expression when evaluating an input, in some cases it can cause performance issues, called catastrophic backtracking situations. In the worst case, the complexity of the regular expression is exponential in the size of the input, this means that a small carefully-crafted input (like 20 chars) can trigger catastrophic backtracking and cause a denial of service of the application. Super-linear regex complexity can lead to the same impact too with, in this case, a large carefully-crafted input (thousands chars).
This rule determines the runtime complexity of a regular expression and informs you of the complexity if it is not linear.
Note that, due to improvements to the matching algorithm, some cases of exponential runtime complexity have become impossible when run using JDK 9 or later. In such cases, an issue will only be reported if the project’s target Java version is 8 or earlier.
The complexity of an expression is defined by the number of &&, || and condition ? ifTrue : ifFalse operators it contains.
A single expression’s complexity should not become too high to keep the code readable.
A cross-site request forgery (CSRF) attack occurs when a trusted user of a web application can be forced, by an attacker, to perform sensitive actions that he didn’t intend, such as updating his profile or sending a message, more generally anything that can change the state of the application.
The attacker can trick the user/victim to click on a link, corresponding to the privileged action, or to visit a malicious web site that embeds a hidden web request and as web browsers automatically include cookies, the actions can be authenticated and sensitive.
Type parameters that aren’t used are dead code, which can only distract and possibly confuse developers during maintenance. Therefore, unused type parameters should be removed.
When executing an OS command and unless you specify the full path to the executable, then the locations in your application’s PATH environment variable will be searched for the executable. That search could leave an opening for an attacker if one of the elements in PATH is a directory under his control.
When arithmetic is performed on integers, the result will always be an integer. You can assign that result to a \`long, double, or float with automatic type conversion, but having started as an int or long, the result will likely not be what you expect.
For instance, if the result of int division is assigned to a floating-point variable, precision will have been lost before the assignment. Likewise, if the result of multiplication is assigned to a long\`, it may have already overflowed before the assignment.
In either case, the result will not be what was expected. Instead, at least one operand should be cast or promoted to the final type before the operation takes place.
Having a permissive Cross-Origin Resource Sharing policy is security-sensitive. It has led in the past to the following vulnerabilities:
Same origin policy in browsers prevents, by default and for security-reasons, a javascript frontend to perform a cross-origin HTTP request to a resource that has a different origin (domain, protocol, or port) from its own. The requested target can append additional HTTP headers in response, called CORS, that act like directives for the browser and change the access control policy / relax the same origin policy.
The use of break and continue statements increases the complexity of the control flow and makes it harder to understand the program logic. In order to keep a good program structure, they should not be applied more than once per loop.
This rule reports an issue when there is more than one break or continue statement in a loop. The code should be refactored to increase readability if there is more than one.
Character classes in regular expressions are a convenient way to match one of several possible characters by listing the allowed characters or ranges of characters. If a character class contains only one character, the effect is the same as just writing the character without a character class.
Thus, having only one character in a character class is usually a simple oversight that remained after removing other characters of the class.
Declaring a variable only to immediately return or throw it is considered a bad practice because it adds unnecessary complexity to the code. This practice can make the code harder to read and understand, as it introduces an extra step that doesn’t add any value. Instead of declaring a variable and then immediately returning or throwing it, it is generally better to return or throw the value directly. This makes the code cleaner, simpler, and easier to understand.
The use of a comparison operator outside of a boolean context is an error. At best it is meaningless code, and should be eliminated. However the far more likely scenario is that it is an assignment gone wrong, and should be corrected.
Development tools and frameworks usually have options to make debugging easier for developers. Although these features are useful during development, they should never be enabled for applications deployed in production. Debug instructions or error messages can leak detailed information about the system, like the application’s path or file names.
In software development, logs serve as a record of events within an application, providing crucial insights for debugging. When logging, it is essential to ensure that the logs are:
easily accessible
uniformly formatted for readability
properly recorded
securely logged when dealing with sensitive data
Those requirements are not met if a program directly writes to the standard outputs (e.g., \{language\_std\_outputs}). That is why defining and using a dedicated logger is highly recommended.
Shadowing makes it impossible to use the type parameter from the outer scope. Also, it can be confusing to distinguish which type parameter is being used.
This rule raises an issue when a type parameter from an inner scope uses the same name as one in an outer scope.
Magic numbers make the code more complex to understand as it requires the reader to have knowledge about the global context to understand the number itself. Their usage may seem obvious when writing the code, but it may not be the case for another developer or later once the context faded away. -1, 0, and 1 are not considered magic numbers.
This rule is meant to be used as a way to track code which is marked as being deprecated. Deprecated code should eventually be removed.
Integer literals starting with a zero are octal rather than decimal values. While using octal values is fully supported, most developers do not have experience with them. They may not recognize octal values as such, mistaking them instead for decimal values.
Using pseudorandom number generators (PRNGs) is security-sensitive. For example, it has led in the past to the following vulnerabilities:
When software generates predictable values in a context requiring unpredictability, it may be possible for an attacker to guess the next value that will be generated, and use this guess to impersonate another user or access sensitive information.
Because it is easy to extract strings from an application source code or binary, secrets should not be hard-coded. This is particularly true for applications that are distributed or that are open-source.
In the past, it has led to the following vulnerabilities:
Secrets should be stored outside of the source code in a configuration file or a management service for secrets.
This rule detects variables/fields having a name matching a list of words (secret, token, credential, auth, api\[\_.-]?key) being assigned a pseudorandom hard-coded value. The pseudorandomness of the hard-coded value is based on its entropy and the probability to be human-readable. The randomness sensibility can be adjusted if needed. Lower values will detect less random values, raising potentially more false positives.
When exceptions occur, it is usually a bad idea to simply ignore them. Instead, it is better to handle them properly, or at least to log them.
Whenever there are portions of code that are duplicated and do not depend on the state of their container class, they can be centralized inside a "utility class". A utility class is a class that only has static members, hence it should not be instantiated.
Successful Zip Bomb attacks occur when an application expands untrusted archive files without controlling the size of the expanded data, which can lead to denial of service. A Zip bomb is usually a malicious archive file of a few kilobytes of compressed data but turned into gigabytes of uncompressed data. To achieve this extreme compression ratio, attackers will compress irrelevant data (eg: a long string of repeated bytes).
An HTTP method is safe when used to perform a read-only operation, such as retrieving information. In contrast, an unsafe HTTP method is used to change the state of an application, for instance to update a user’s profile on a web application.
Common safe HTTP methods are GET, HEAD, or OPTIONS.
Common unsafe HTTP methods are POST, PUT and DELETE.
Allowing both safe and unsafe HTTP methods to perform a specific operation on a web application could impact its security, for example CSRF protections are most of the time only protecting operations performed by unsafe HTTP methods.
Nested code - blocks of code inside blocks of code - is eventually necessary, but increases complexity. This is why keeping the code as flat as possible, by avoiding unnecessary nesting, is considered a good practice.
Merging if statements when possible will decrease the nesting of the code and improve its readability.
An empty \{operationName} is generally considered bad practice and can lead to confusion, readability, and maintenance issues. Empty \{operationName}s bring no functionality and are misleading to others as they might think the \{operationName} implementation fulfills a specific and identified requirement.
There are several reasons for a \{operationName} not to have a body:
It is an unintentional omission, and should be fixed to prevent an unexpected behavior in production.
It is not yet, or never will be, supported. In this case an exception should be thrown.
The method is an intentionally-blank override. In this case a nested comment should explain the reason for the blank override.
One way to test for empty lines is to use the regex \`"^\$", which can be extremely handy when filtering out empty lines from collections of Strings, for instance. With regard to this, the Javadoc for Pattern (Line Terminators) states the following:
By default, the regular expressions ^ and $ignore line terminators and only match at the beginning and the end, respectively, of the entire input sequence. If MULTILINE mode is activated then ^ matches at the beginning of input and after any line terminator except at the end of input. When in MULTILINE mode$ matches just before a line terminator or the end of the input sequence.
As emphasized, ^ is not going to match at the end of an input, and the end of the input is necessarily included in the empty string, which might lead to completely missing empty lines, while it would be the initial reason for using such regex.
Therefore, when searching for empty lines using a multi-line regular expression, you should also check whether the string is empty.
This rule is raising an issue every time a pattern that can match the empty string is used with MULTILINE flag and without calling isEmpty()\` on the string.
Using upper case literal suffixes removes the potential ambiguity between "1" (digit 1) and "l" (letter el) for declaring literals.
Lookahead assertions are a regex feature that makes it possible to look ahead in the input without consuming it. It is often used at the end of regular expressions to make sure that substrings only match when they are followed by a specific pattern.
For example, the following pattern will match an "a" only if it is directly followed by a "b". This does not consume the "b" in the process:
Unresolved directive in \
However, lookaheads can also be used in the middle (or at the beginning) of a regex. In that case there is the possibility that what comes after the lookahead contradicts the pattern inside the lookahead. Since the lookahead does not consume input, this makes the lookahead impossible to match and is a sign that there’s a mistake in the regular expression that should be fixed.
Clear-text protocols such as \`ftp, telnet, or http lack encryption of transported data, as well as the capability to build an authenticated connection. It means that an attacker able to sniff traffic from the network can read, modify, or corrupt the transported content. These protocols are not secure as they expose applications to an extensive range of risks:
sensitive data exposure
traffic redirected to a malicious endpoint
malware-infected software update or installer
execution of client-side code
corruption of critical information
Even in the context of isolated networks like offline environments or segmented cloud environments, the insider threat exists. Thus, attacks involving communications being sniffed or tampered with can still happen.
For example, attackers could successfully compromise prior security layers by:
bypassing isolation mechanisms
compromising a component of the network
getting the credentials of an internal IAM account (either from a service account or an actual person)
In such cases, encrypting communications would decrease the chances of attackers to successfully leak data or steal credentials from other network components. By layering various security practices (segmentation and encryption, for example), the application will follow the defense-in-depth principle.
Note that using the http\` protocol is being deprecated by major web browsers.
In the past, it has led to the following vulnerabilities:
When a cookie is configured with the HttpOnly attribute set to true, the browser guaranties that no client-side script will be able to read it. In most cases, when a cookie is created, the default value of HttpOnly is false and it’s up to the developer to decide whether or not the content of the cookie can be read by the client-side script. As a majority of Cross-Site Scripting (XSS) attacks target the theft of session-cookies, the HttpOnly attribute can help to reduce their impact as it won’t be possible to exploit the XSS vulnerability to steal session-cookies.
Array designators should always be located on the type for better code readability. Otherwise, developers must look both at the type and the variable name to know whether or not a variable is an array.
If a private field is declared but not used locally, its limited visibility makes it dead code.
This is either a sign that some logic is missing or that the code should be cleaned.
Cleaning out dead code decreases the size of the maintained codebase, making it easier to understand and preventing bugs from being introduced.
Casting expressions are utilized to convert one data type to another, such as transforming an integer into a string. This is especially crucial in strongly typed languages like C, C++, C#, Java, Python, and others.
However, there are instances where casting expressions are not needed. These include situations like:
casting a variable to its own type
casting a subclass to a parent class (in the case of polymorphism)
the programming language is capable of automatically converting the given type to another
These scenarios are considered unnecessary casting expressions. They can complicate the code and make it more difficult to understand, without offering any advantages.
As a result, it’s generally advised to avoid unnecessary casting expressions. Instead, rely on the language’s type system to ensure type safety and code clarity.
A regular expression is a sequence of characters that specifies a match pattern in text. Among the most important concepts are:
Character classes: defines a set of characters, any one of which can occur in an input string for a match to succeed.
Quantifiers: used to specify how many instances of a character, group, or character class must be present in the input for a match.
Wildcard (.): matches all characters except line terminators (also matches them if the s flag is set).
Many of these features include shortcuts of widely used expressions, so there is more than one way to construct a regular expression to achieve the same results. For example, to match a two-digit number, one could write \[0-9]\{2,2} or \d\{2}. The latter is not only shorter but easier to read and thus to maintain.
This rule recommends replacing some quantifiers and character classes with more concise equivalents:
\d for \[0-9] and \D for \[^0-9]
\w for \[A-Za-z0-9\_] and \W for \`\[^A-Za-z0-9\_]
. for character classes matching everything (e.g. \[\w\W], \[\d\D], or \[\s\S] with s flag)
x? for x\{0,1}, x\* for x\{0,}, x+ for x\{1,}, x\{N} for x\{N,N}\`
Arbitrary OS command injection vulnerabilities are more likely when a shell is spawned rather than a new process, indeed shell meta-chars can be used (when parameters are user-controlled for instance) to inject OS commands.
Even if it is legal, mixing case and non-case labels in the body of a switch statement is very confusing and can even be the result of a typing error.
Using the same value on both sides of a binary operator is a code defect. In the case of logical operators, it is either a copy/paste error and, therefore, a bug, or it is simply duplicated code and should be simplified. In the case of bitwise operators and most binary mathematical operators, having the same value on both sides of an operator yields predictable results and should be simplified as well.
When either the equality operator in a null test or the logical operator that follows it is reversed, the code has the appearance of safely null-testing the object before dereferencing it. Unfortunately the effect is just the opposite - the object is null-tested and then dereferenced only if it is null, leading to a guaranteed null pointer dereference.
Rejecting requests with significant content length is a good practice to control the network traffic intensity and thus resource consumption in order to prevent DoS attacks.
A common code smell that can hinder the clarity of source code is making assignments within sub-expressions. This practice involves assigning a value to a variable inside a larger expression, such as within a loop or a conditional statement.
This practice essentially gives a side-effect to a larger expression, thus making it less readable. This often leads to confusion and potential errors.
A chain of if/else if statements is evaluated from top to bottom. At most, only one branch will be executed: the first one with a condition that evaluates to true.
Therefore, duplicating a condition automatically leads to dead code. Usually, this is due to a copy/paste error. At best, it’s simply dead code and at worst, it’s a bug that is likely to induce further bugs as the code is maintained, and obviously it could lead to unexpected behavior.
In regular expressions the boundaries \`^ and \A can only match at the beginning of the input (or, in case of ^ in combination with the MULTILINE flag, the beginning of the line) and \$, \Z and \z only at the end.
These patterns can be misused, by accidentally switching ^ and \$\` for example, to create a pattern that can never match.
Formatted SQL queries can be difficult to maintain, debug and can increase the risk of SQL injection when concatenating untrusted values into the query. However, this rule doesn’t detect SQL injections (unlike rule S3649), the goal is only to highlight complex/formatted queries.
A typical code smell known as unused function parameters refers to parameters declared in a function but not used anywhere within the function’s body. While this might seem harmless at first glance, it can lead to confusion and potential errors in your code. Disregarding the values passed to such parameters, the function’s behavior will be the same, but the programmer’s intention won’t be clearly expressed anymore. Therefore, removing function parameters that are not being utilized is considered best practice.
Public fields in public classes do not respect the encapsulation principle and have three main disadvantages:
Additional behavior such as validation cannot be added.
The internal representation is exposed, and cannot be changed afterwards.
Member values are subject to change from anywhere in the code and may not meet the programmer’s assumptions.
To prevent unauthorized modifications, private attributes and accessor methods (set and get) should be used.
Storing data locally is a common task for mobile applications. Such data includes files among other things. One convenient way to store files is to use the external file storage which usually offers a larger amount of disc space compared to internal storage.
Files created on the external storage are globally readable and writable. Therefore, a malicious application having the permissions WRITE\_EXTERNAL\_STORAGE or READ\_EXTERNAL\_STORAGE could try to read sensitive information from the files that other applications have stored on the external storage.
External storage can also be removed by the user (e.g when based on SD card) making the files unavailable to the application.
When placing Unicode Grapheme Clusters (characters which require to be encoded in multiple Code Points) inside a character class of a regular expression, this will likely lead to unintended behavior.
For instance, the grapheme cluster c̈ requires two code points: one for 'c', followed by one for the umlaut modifier '\u\{0308}'. If placed within a character class, such as \[c̈], the regex will consider the character class being the enumeration \[c\u\{0308}] instead. It will, therefore, match every 'c' and every umlaut that isn’t expressed as a single codepoint, which is extremely unlikely to be the intended behavior.
This rule raises an issue every time Unicode Grapheme Clusters are used within a character class of a regular expression.
Shared naming conventions improve readability and allow teams to collaborate efficiently. This rule checks that all package names match a provided regular expression.
Constructing arguments of system commands from user input is security-sensitive. It has led in the past to the following vulnerabilities:
Arguments of system commands are processed by the executed program. The arguments are usually used to configure and influence the behavior of the programs. Control over a single argument might be enough for an attacker to trigger dangerous features like executing arbitrary commands or writing files into specific directories.
Hard-coding a URI makes it difficult to test a program for a variety of reasons:
path literals are not always portable across operating systems
a given absolute path may not exist in a specific test environment
a specified Internet URL may not be available when executing the tests
production environment filesystems usually differ from the development environment
In addition, hard-coded URIs can contain sensitive information, like IP addresses, and they should not be stored in the code.
For all those reasons, a URI should never be hard coded. Instead, it should be replaced by a customizable parameter.
Further, even if the elements of a URI are obtained dynamically, portability can still be limited if the path delimiters are hard-coded.
This rule raises an issue when URIs or path delimiters are hard-coded.
This rule applies whenever an \`if statement is followed by one or more else if statements; the final else if should be followed by an else statement.
The requirement for a final else statement is defensive programming.
The else statement should either take appropriate action or contain a suitable comment as to why no action is taken. This is consistent with the requirement to have a final default clause in a switch\` statement.
To reduce the risk of cross-site scripting attacks, templating systems, such as \`Twig, Django, Smarty, Groovy's template engine, allow configuration of automatic variable escaping before rendering templates. When escape occurs, characters that make sense to the browser (eg: \) will be transformed/replaced with escaped/sanitized values (eg: & lt;a& gt; ).
Auto-escaping is not a magic feature to annihilate all cross-site scripting attacks, it depends on the strategy applied and the context, for example a "html auto-escaping" strategy (which only transforms html characters into html entities) will not be relevant when variables are used in a html attribute because ':’ character is not escaped and thus an attack as below is possible:
Multiple spaces in a regular expression can make it hard to tell how many spaces should be matched. It’s more readable to use only one space and then indicate with a quantifier how many spaces are expected.
User-provided data, such as URL parameters, POST data payloads, or cookies, should always be considered untrusted and tainted. Applications constructing HTTP response headers based on tainted data could allow attackers to change security sensitive headers like Cross-Origin Resource Sharing headers.
Web application frameworks and servers might also allow attackers to inject new line characters in headers to craft malformed HTTP response. In this case the application would be vulnerable to a larger range of attacks like HTTP Response Splitting/Smuggling. Most of the time this type of attack is mitigated by default modern web application frameworks but there might be rare cases where older versions are still vulnerable.
As a best practice, applications that use user-provided data to construct the response header should always validate the data first. Validation should be based on a whitelist.
Android applications can receive broadcasts from the system or other applications. Receiving intents is security-sensitive. For example, it has led in the past to the following vulnerabilities:
Receivers can be declared in the manifest or in the code to make them context-specific. If the receiver is declared in the manifest Android will start the application if it is not already running once a matching broadcast is received. The receiver is an entry point into the application.
Other applications can send potentially malicious broadcasts, so it is important to consider broadcasts as untrusted and to limit the applications that can send broadcasts to the receiver.
Permissions can be specified to restrict broadcasts to authorized applications. Restrictions can be enforced by both the sender and receiver of a broadcast. If permissions are specified when registering a broadcast receiver, then only broadcasters who were granted this permission can send a message to the receiver.
This rule raises an issue when a receiver is registered without specifying any broadcast permission.
When a cookie is protected with the secure attribute set to true it will not be send by the browser over an unencrypted HTTP request and thus cannot be observed by an unauthorized person during a man-in-the-middle attack.
If a label is declared but not used in the program, it can be considered as dead code and should therefore be removed.
This will improve maintainability as developers will not wonder what this label is used for.
Android comes with Android KeyStore, a secure container for storing key materials. It’s possible to define certain keys to be unlocked when users authenticate using biometric credentials. This way, even if the application process is compromised, the attacker cannot access keys, as presence of the authorized user is required.
These keys can be used, to encrypt, sign or create a message authentication code (MAC) as proof that the authentication result has not been tampered with. This protection defeats the scenario where an attacker with physical access to the device would try to hook into the application process and call the \`onAuthenticationSucceeded method directly. Therefore he would be unable to extract the sensitive data or to perform the critical operations protected by the biometric authentication.
The application contains:
Cryptographic keys / sensitive information that need to be protected using biometric authentication.
There is a risk if you answered yes to this question.
It’s recommended to tie the biometric authentication to a cryptographic operation by using a CryptoObject\` during authentication.
Why use named groups only to never use any of them later on in the code?
This rule raises issues every time named groups are:
defined but never called anywhere in the code through their name;
defined but called elsewhere in the code by their number instead;
referenced while not defined.
Nested control flow statements such as if, for, while, switch, and try are often key ingredients in creating
what’s known as "Spaghetti code". This code smell can make your program difficult to understand and maintain.
When numerous control structures are placed inside one another, the code becomes a tangled, complex web. This significantly reduces the code’s readability and maintainability, and it also complicates the testing process.
There is no good reason to create a new object to not do anything with it. Most of the time, this is due to a missing piece of code and so could lead to an unexpected behavior in production.
If it was done on purpose because the constructor has side-effects, then that side-effect code should be moved into a separate method and called directly.
A catch clause that only rethrows the caught exception has the same effect as omitting the catch altogether and letting it bubble up automatically.
Unresolved directive in \
Such clauses should either be removed or populated with the appropriate logic.
Unresolved directive in \
Overriding a method just to call the same method from the super class without performing any other actions is useless and misleading. The only time this is justified is in final overriding methods, where the effect is to lock in the parent class behavior. This rule ignores such overrides of equals, hashCode and toString.
Duplicated string literals make the process of refactoring complex and error-prone, as any change would need to be propagated on all occurrences.
Altering or bypassing the accessibility of classes, methods, or fields through reflection violates the encapsulation principle. This can break the internal contracts of the accessed target and lead to maintainability issues and runtime errors.
This rule raises an issue when reflection is used to change the visibility of a class, method or field, and when it is used to directly update a field value.
When the value of a private field is always assigned to in a class' methods before being read, then it is not being used to store class information. Therefore, it should become a local variable in the relevant methods to prevent any misunderstanding.
There are various String operations that take one or more character indexes as arguments and return a portion of the original string. Indexing in this context is zero-based, meaning that the first character’s index is 0. As a result, given a string myString, its last character is at index myString.length() - 1.
The String operation methods throw a StringIndexOutOfBoundsException when one of their index argument is smaller than 0 (E.G.: -1). String::substring also throws this exception when the beginIndex or endIndex argument is larger than myString.length(), and String::charAt when the index argument is larger than myString.length() - 1 For instance, it is not possible to use String::charAt to retrieve a value before the start or after the end of a string. Furthermore, it is not possible to use String::substring with beginIndex > endIndex to reverse the order of characters in a string.
This rule raises an issue when a negative literal or an index that is too large is passed as an argument to the String::substring, String::charAt, and related methods. It also raises an issue when the start index passed to String::substring is larger than the end index.
Executing a batch of SQL queries instead of individual queries improves performance by reducing communication overhead with the database.
Batching SQL statements is beneficial in common situations where a SQL statement is executed within a loop. In such cases, adding the statement to a batch and subsequently executing it reduces the number of interactions with the database. This results in improved efficiency and faster execution times.
The rule raises an issue when it detects a java.sql.Statement being executed within a loop instruction, such as for, while or the forEach method of java.lang.Iterable, java.util.Map and java.util.stream.Stream.
When using the \`Stream API, call chains should be simplified as much as possible to improve readability and maintainability.
This rule raises an issue when one of the following substitution can be made:
| Original | Preferred |
|---|---|
stream.collect(counting()) |
stream.count() |
stream.collect(maxBy(comparator)) |
stream.max(comparator) |
stream.collect(minBy(comparator)) |
stream.min(comparator) |
stream.collect(mapping(mapper)) |
stream.map(mapper).collect() |
stream.collect(reducing(...)) |
stream.reduce(...) |
stream.collect(summingInt(mapper)) |
stream.mapToInt(mapper).sum() |
stream.collect(summingLong(mapper)) |
stream.mapToLong(mapper).sum() |
stream.collect(summingDouble(mapper)) |
stream.mapToDouble(mapper).sum()\` |
Synchronization can be expensive in terms of time when multiple threads need to pass through the same bottleneck /\`synchronized piece of code.
If you have a piece of code calling a synchronized method once, then it only has to wait its turn to pass through the bottleneck once. But call it in a loop, and your code has to get back in line for the bottleneck over and over.
Instead, it would be better to get into the bottleneck, and then do the looping. I.e. consider refactoring the code to perform the loop inside the synchronized method.
This rule raises an issue when a synchronized\` method is called in a loop.
It can be useful to use in-code notation to suppress issues, but when those suppressions are no longer relevant they become a potential source of confusion and should be removed.
Optional acts as a container object that may or may not contain a non-null value. It is introduced in Java 8 to help avoid NullPointerException. It provides methods to check if a value is present and retrieve the value if it is present.
Optional is used instead of null values to make the code more readable and avoid potential errors.
It is a bad practice to use null with Optional because it is unclear whether a value is present or not, leading to confusion and potential NullPointerException errors.
Fields, parameters and return values marked `@NotNull, @NonNull, or @Nonnull are assumed to have non-null values and are not typically null-checked before use. Therefore setting one of these values to null, or failing to set such a class field in a constructor, could cause NullPointerException`s at runtime.
When a reluctant quantifier (such as \`\*? or +?) is followed by a pattern that can match the empty string or directly by the end of the regex, it will always match the empty string when used with methods that find partial matches (such as find, replaceAll, split etc.).
Similarly, when used with methods that find full matches, a reluctant quantifier that’s followed directly by the end of the regex (or a pattern that always matches the empty string, such as ()\`) behaves indistinguishably from a greedy quantifier while being less efficient.
This is likely a sign that the regex does not work as intended.
A non-serializable Comparator can prevent an otherwise-Serializable ordered collection from being serializable. Since the overhead to make a Comparator serializable is usually low, doing so can be considered good defensive programming.
In Java, numeric promotions happen when two operands of an arithmetic expression have different sizes. More specifically, narrower operands get promoted to the type of wider operands. For instance, an operation between a byte and an int, will trigger a promotion of the byte operand, converting it into an int.
When this happens, the sequence of 8 bits that represents the byte will need to be extended to match the 32-bit long sequence that represents the int operand. Since Java uses two’s complement notation for signed number types, the promotion will fill the missing leading bits with zeros or ones, depending on the sign of the value. For instance, the byte 0b1000\_0000 (equal to -128 in decimal notation), when promoted to int, will become 0b1111\_1111\_1111\_1111\_1111\_1111\_1000\_0000.
When performing shifting or bitwise operations without considering that bytes are signed, the bits added during the promotion may have unexpected effects on the final result of the operations.
Naming conventions play a crucial role in maintaining code clarity and readability. The uniqueness of bean names in Spring configurations is vital to the clarity and readability of the code. When two beans share the same name within a configuration, it is not obvious to the reader which bean is being referred to. This leads to potential misunderstandings and errors.
When @Overrides of synchronized methods are not themselves synchronized, the result can be improper synchronization as callers rely on the thread-safety promised by the parent class.
In a multithreaded environment, the Object.wait(…), as well as Condition.await(…) and similar methods are used to pause the execution of a thread until the thread is awakened. A thread is typically awakened when it is notified, signaled, or interrupted, usually because of an event in another thread requiring some subsequent action by the waiting thread.
However, a thread may be awakened despite the desired condition not being met or the desired event not having happened. This is referred to as "spurious wakeups" and may be caused by underlying platform semantics. In other words, a thread may be awakened due to reasons that have nothing to do with the business logic. Hence, the assumption that the desired condition is met or the desired event occurred after a thread is awakened does not always hold.
According to the documentation of the Java Condition interface \[1]:
When waiting upon a Condition, a "spurious wakeup" is permitted to occur, in general, as a concession to the underlying platform semantics. This has little practical impact on most application programs as a Condition should always be waited upon in a loop, testing the state predicate that is being waited for. An implementation is free to remove the possibility of spurious wakeups but it is recommended that applications programmers always assume that they can occur and so always wait in a loop.
The same advice is also found for the Object.wait(…) method \[2]:
\[…] waits should always occur in loops, like this one:
synchronized (obj) \{ while (\)\{ obj.wait(timeout); } ... // Perform action appropriate to condition }
The use of unnecessary types makes the eye stumble, and inhibits the smooth reading of code.
The underlying implementation of \`String::replaceAll calls the java.util.regex.Pattern.compile() method each time it is called even if the first argument is not a regular expression. This has a significant performance cost and therefore should be used with care.
When String::replaceAll is used, the first argument should be a real regular expression. If it’s not the case, String::replace does exactly the same thing as String::replaceAll without the performance drawback of the regex.
This rule raises an issue for each String::replaceAll used with a String\` as first parameter which doesn’t contains special regex character or pattern.
Before it reclaims storage from an object that is no longer referenced, the garbage collector calls finalize() on the object.
But there is no guarantee that this method will be called as soon as the last references to the object are removed.
It can be few microseconds to few minutes later.
For this reason relying on overriding the finalize() method to release resources or to update the state of the program is highly discouraged.
Creating an object for the sole purpose of calling getClass on it is a waste of memory and cycles. Instead, simply use the class’s .class property.
Thread.yield is intended to hint to the processor that the current thread is willing to suspended in favor of another thread. Unfortunately, it doesn’t have the same results across platforms, thus marring the cross-platform compatibility of any application that uses it.
Java 21 introduces the new Sequenced Collections API, which is applicable to all collections with a defined sequence on their elements, such as LinkedList, TreeSet, and others (see JEP 431). For projects using Java 21 and onwards, this API should be used instead of workaround implementations that were necessary prior to Java 21.
This rule identifies instances where a workaround is used to add or remove the first or last element of a collection where the addFirst, addLast, removeFirst or removeLast method in the java.util.SequencedCollection class should have been used instead.
instanceof operators that always return true or false are either useless or the result of a misunderstanding which could lead to unexpected behavior in production.
Shared coding conventions allow teams to collaborate efficiently. This rule checks that all local, final, initialized, primitive variables, have names that match a provided regular expression.
A Spring @Controller that uses @SessionAttributes is designed to handle a stateful / multi-post form. Such @Controllers use the specified @SessionAttributes to store data on the server between requests. That data should be cleaned up when the session is over, but unless setComplete() is called on the SessionStatus object from a @RequestMapping method, neither Spring nor the JVM will know it’s time to do that. Note that the SessionStatus object must be passed to that method as a parameter.
Spring \`@Controllers, @Services, and @Repositorys have singleton scope by default, meaning only one instance of the class is ever instantiated in the application. Defining any other scope for one of these class types will result in needless churn as new instances are created and destroyed. In a busy web application, this could cause a significant amount of needless additional load on the server.
This rule raises an issue when the @Scope annotation is applied to a @Controller, @Service, or @Repository with any value but "singleton". @Scope("singleton")\` is redundant, but ignored.
Java 8 introduced \`ThreadLocal.withInitial which is a simpler alternative to creating an anonymous inner class to initialise a ThreadLocal instance.
This rule raises an issue when a ThreadLocal anonymous inner class can be replaced by a call to ThreadLocal.withInitial\`.
java.util.concurrent.locks.Lock offers far more powerful and flexible locking operations than are available with synchronized blocks. So synchronizing on a Lock instance throws away the power of the object, as it overrides its better locking mechanisms. Instead, such objects should be locked and unlocked using one of their lock and unlock method variants.
Floating point math is imprecise because of the challenges of storing such values in a binary representation. Even worse, floating point math is not associative; push a \`float or a double through a series of simple mathematical operations and the answer will be different based on the order of those operation because of the rounding that takes place at each step.
Even simple floating point assignments are not simple:
float f = 0.1; // 0.100000001490116119384765625
double d = 0.1; // 0.1000000000000000055511151231257827021181583404541015625
(Results will vary based on compiler and compiler settings);
Therefore, the use of the equality (==) and inequality (!=) operators on float or double values is almost always an error. Instead the best course is to avoid floating point comparisons altogether. When that is not possible, you should consider using one of Java’s float-handling Numbers such as BigDecimal which can properly handle floating point comparisons. A third option is to look not for equality but for whether the value is close enough. I.e. compare the absolute value of the difference between the stored value and the expected value against a margin of acceptable error. Note that this does not cover all cases (NaN and Infinity\` for instance).
This rule checks for the use of direct and indirect equality/inequailty tests on floats and doubles.
Persistence annotations should be marked either on fields or on getters but not on both. Mix the two and the annotated fields will be ignored. The potential results are that your database tables are not created or not populated (and read) correctly.
AssertJ contains many assertions methods specific to common types. Both versions will test the same things, but the dedicated one will provide a better error message, simplifying the debugging process.
This rule reports an issue when an assertion can be simplified to a dedicated one.
The array below gives a non-exhaustive list of assertion reported by the rule. Code behaving similarly, or with a negation will also be reported.
| Original | Dedicated |
|---|---|
Related to Object |
|
\`assertThat(getObject()).isEqualTo(null) |
assertThat(getObject()).isNull() |
assertThat(getBoolean()).isEqualTo(true) |
assertThat(getBoolean()).isTrue() |
assertThat(getBoolean()).isEqualTo(false) |
assertThat(getBoolean()).isFalse() |
assertThat(x.equals(y)).isTrue() |
assertThat(x).isEqualTo(y) |
@Configuration is a class-level annotation indicating that an object is a source of bean definitions. @Configuration classes declare beans through @Bean-annotated methods. Calls to @Bean methods on @Configuration classes can also be used to define inter-bean dependencies. The @Bean annotation indicates that a method instantiates, configures, and initializes a new object to be managed by the Spring IoC container.
Annotating a method of a bean with @Async will make it execute in a separate thread. In other words, the caller will not wait for the completion of the called method.
The @Async annotation is not supported on methods declared within a @Configuration class. This is because @Async methods are typically used for asynchronous processing, and they require certain infrastructure to be set up, which may not be available or appropriate in a @Configuration class.
The purpose of the hashCode method is to return a hash code based on the contents of the object. Similarly, the purpose of the toString method is to provide a textual representation of the object’s contents.
Calling hashCode() and toString() directly on array instances should be avoided because the default implementations provided by the Object class do not provide meaningful results for arrays. hashCode() returns the array’s "identity hash code", and toString() returns nearly the same value. Neither method’s output reflects the array’s contents.
When boxed type java.lang.Boolean is used as an expression to determine the control flow (as described in Java Language Specification §4.2.5 The boolean Type and boolean Values) it will throw a NullPointerException if the value is null (as defined in Java Language Specification §5.1.8 Unboxing Conversion).
It is safer to avoid such conversion altogether and handle the null value explicitly.
Note, however, that no issues will be raised for Booleans that have already been null-checked.
The java.util.Iterator.next() method must throw a NoSuchElementException when there are no more elements in the iteration. Any other behavior is non-compliant with the API contract and may cause unexpected behavior for users.
A serialVersionUID field is required in a Serializable class. In a non-Serializable, it’s just confusing.
Method references are specialized lambda expressions for methods that already have a name. They take the form of objectReference::methodName or ClassName::methodName. When a lambda does nothing but call an existing method, it can be much clearer to use a method reference instead.
Recursion is a technique to solve a computational problem by splitting it into smaller problems. A method is recursive, if it splits its input into smaller instances and calls itself on these instances. This continues until a smallest input, a base case, is reached that can not be split further. Similarly, recursion can also occur when multiple methods invoke each other.
Recursion is a useful tool, but it must be used carefully. Recursive methods need to detect base cases and end recursion with a return statement.
When this is not the case, recursion will continue until the stack overflows and the
program crashes due to a StackOverflowError.
Just as there is little justification for writing your own String class, there is no good reason to re-define one of the existing, standard functional interfaces.
Doing so may seem tempting, since it would allow you to specify a little extra context with the name. But in the long run, it will be a source of confusion, because maintenance programmers will wonder what is different between the custom functional interface and the standard one.
The use of Unicode escape sequences should be reserved for characters that would otherwise be ambiguous, such as unprintable characters.
This rule ignores sequences composed entirely of Unicode characters, but otherwise raises an issue for each Unicode character that represents a printable character.
The use of factory methods lets you abstract the job you need to do from the specific tool implementations needed to do it with, and helps insulate you from changes.
This rule raises an issue when instances of these are instantiated directly:
\`javax.xml.parsers.DocumentBuilder
javax.xml.parsers.SAXParser
javax.xml.transform.Transformer
org.xml.sax.XMLReader
org.xml.sax.XMLFilter
org.w3c.dom.\*\`
Empty implementations of the \`X509TrustManager interface are often created to allow connection to a host that is not signed by a root certificate authority. Such an implementation will accept any certificate, which leaves the application vulnerable to Man-in-the-middle attacks. The correct solution is to provide an appropriate trust store.
This rule raises an issue when an implementation of X509TrustManager\` never throws exception.
The Spring dependency injection mechanism cannot identify which constructor to use for auto-wiring when multiple constructors are present in a class. This ambiguity can cause the application to crash at runtime, and it makes the code less clear to understand and more complex to extend and maintain.
In Java 10 Local-Variable Type Inference was introduced. It allows you to omit the expected type of a variable by declaring it with the \`var keyword.
While it is not always possible or cleaner to use this new way of declaring a variable, when the type on the left is the same as the one on the right in an assignment, using the var\` will result in a more concise code.
This rule reports an issue when the expected type of the variable is the same as the returned type of assigned expression and the type can be easily inferred by the reader, either when the type is already mentioned in the name or the initializer, or when the expression is self-explanatory.
It is very common to pass a collection constructor reference as an argument, for example \`Collectors.toCollection(ArrayList::new) takes the ArrayList::new constructor. When the method expects a java.util.function.Supplier it is perfectly fine. However when the method argument type is java.util.function.Function it means that an argument will be passed to the constructor.
The first argument of Collections constructors is usually an integer representing its "initial capacity". This is generally not what the developer expects, but the memory allocation is not visible at first glance.
This rule raises an issue when a collection constructor is passed by reference as a java.util.function.Function\` argument.
Superfluous exceptions within throws clauses have negative effects on the readability and maintainability of the code. An exception in a throws clause is superfluous if it is:
listed multiple times
a subclass of another listed exception
not actually thrown by any execution path of the method
If the \`suite method in a JUnit 3 TestCase is not declared correctly, it will not be used. Such a method must be named "suite", have no arguments, be public static, and must return either a junit.framework.Test or a junit.framework.TestSuite.
Similarly, setUp and tearDown\` methods that aren’t properly capitalized will also be ignored.
In Java 8 Streams were introduced to support chaining of operations over collections in a functional style. The most common way to save a result of such chains is to save them to some collection (usually List). To do so there is a terminal method collect that can be used with a library of Collectors. The key problem is that .collect(Collectors.toList()) actually returns a mutable kind of List while in the majority of cases unmodifiable lists are preferred. In Java 10 a new collector appeared to return an unmodifiable list: toUnmodifiableList(). This does the trick but results in verbose code. Since Java 16 there is now a better variant to produce an unmodifiable list directly from a stream: Stream.toList().
This rule raises an issue when "collect" is used to create a list from a stream.
There are several reasons that a class might have a method that throws an \`UnsupportedOperationException. The method may be required by an interface or an abstract superclass but not actually needed in the class. Or it may be that the class itself is intended as a superclass, and the method may optionally be implemented by subclasses but not invoked on the superclass. Finally, it could be that the method has been stubbed into the code but not implemented yet.
Whatever the reason, methods that throw UnsupportedOperationException\` should not be called.
The rules of operator precedence are complicated and can lead to errors. For this reason, parentheses should be used for clarification in complex statements. However, this does not mean that parentheses should be gratuitously added around every operation.
This rule raises issues when \`&& and || are used in combination, when assignment and equality or relational operators are used together in a condition, and for other operator combinations according to the following table:
| +, -, \*, /, % | \<\<, >>, >>> | & | ^ | | | |
|---|---|---|---|---|---|
+, -, \*, /, % |
x |
x |
x |
x |
|
\<\<, >>, >>> |
x |
x |
x |
x |
|
& |
x |
x |
x |
x |
|
^ |
x |
x |
x |
x |
|
|\` |
x |
x |
x |
x |
This rule also raises an issue when the "true" or "false" expression of a ternary operator is not trivial and not wrapped inside parentheses.
There’s no reason to use literal boolean values or nulls in assertions. Instead of using them with assertEquals, assertNotEquals and similar methods, you should be using assertTrue, assertFalse, assertNull or assertNotNull instead (or isNull etc. when using Fest). Using them with assertions unrelated to equality (such as assertNull) is most likely a bug.
Supported frameworks:
JUnit3
JUnit4
JUnit5
Fest assert
In Records serialization is not done the same way as for ordinary serializable or externalizable classes. Records serialization does not rely on the \`serialVersionUID field, because the requirement to have this field equal is waived for record classes. By default, all records will have this field equal to 0L and there is no need to specify this field with 0L value and it is possible to specify it with some custom value to support serialization/deserialization involving ordinary classes.
This rule raises an issue when there is a private static final long serialVersionUID field which is set to 0L\` in a Record class.
The Java Persistence API specification imposes only a conditional requirement that \`@Entity classes be Serializable:
If an entity instance is to be passed by value as a detached object (e.g., through a remote interface), the entity class must implement the Serializable interface.
But it’s best practice to make all such classes Serializable from the start. So this rule raises an issue when an @Entity does not implement Serializable\`.
Synchronization is a mechanism used when multithreading in Java to ensure that only one thread executes a given block of code at a time. This is done to avoid bugs that can occur when multiple threads share a given state and try to manipulate simultaneously.
Object serialization is not thread-safe by default. In a multithreaded environment, one option is to mark writeObject with synchronized to improve thread safety. It is highly suspicious, however, if writeObject is the only synchronized method in a class. It may indicate that serialization is not required, as multithreading is not used. Alternatively, it could also suggest that other methods in the same class have been forgotten to be made thread-safe.
When a back reference in a regex refers to a capturing group that hasn’t been defined yet (or at all), it can never be matched. Named back references throw a \`PatternSyntaxException in that case; numeric back references fail silently when they can’t match, simply making the match fail.
When the group is defined before the back reference but on a different control path (like in (.)|\1\` for example), this also leads to a situation where the back reference can never match.
The compiler automatically initializes class fields to their default values before setting them with any initialization values, so there is no need to explicitly set a field to its default value. Further, under the logic that cleaner code is better code, it’s considered poor style to do so.
All classes extend Object implicitly. Doing so explicitly is redundant.
Further, declaring the implementation of an interface and one if its parents is also redundant. If you implement the interface, you also implicitly implement its parents and there’s no need to do so explicitly.
According to its JavaDocs, the intermediate Stream operation \`java.util.Stream.peek() “exists mainly to support debugging” purposes.
A key difference with other intermediate Stream operations is that the Stream implementation is free to skip calls to peek() for optimization purpose. This can lead to peek() being unexpectedly called only for some or none of the elements in the Stream.
As a consequence, relying on peek()\` without careful consideration can lead to error-prone code.
This rule raises an issue for each use of peek() to be sure that it is challenged and validated by the team to be meant for production debugging/logging purposes.
Using high power consumption modes for Bluetooth operations can drain the device battery faster and may not be suitable for scenarios where power efficiency is crucial.
This rule identifies instances where high power consumption Bluetooth operations are used, specifically when requestConnectionPriority or setAdvertiseMode methods are invoked with arguments other than those promoting low power consumption.
It is very easy to write incomplete assertions when using some test frameworks. This rule enforces complete assertions in the following cases:
Fest: \`assertThat is not followed by an assertion invocation
AssertJ: assertThat is not followed by an assertion invocation
Mockito: verify is not followed by a method invocation
Truth: assertXXX\` is not followed by an assertion invocation
In such cases, what is intended to be a test doesn’t actually verify anything
Regardless of the logging framework in use (logback, log4j, commons-logging, java.util.logging, …), loggers should be:
\`private: never be accessible outside of its parent class. If another class needs to log something, it should instantiate its own logger.
static: not be dependent on an instance of a class (an object). When logging something, contextual information can of course be provided in the messages but the logger should be created at class level to prevent creating a logger along with each object.
final\`: be created once and only once per class.
Using a type parameter when you don’t have to simply obfuscates the code. Inserting an unnecessary type parameter in an unparameterized method call will compile, but confuse maintainers.
Java uses angular brackets (\[/code> and \) to provide a specific type (the "type argument") to a generic type.
For instance, List is a generic type, so a list containing strings can be declared with List\
Prior to Java 7, the type argument had to be provided explicitly for every occurrence where generics were used. This often caused redundancy, as the type argument would have to be provided both when a field is declared and initialized.
Java 7 introduced the diamond operator (\<>) to reduce the code’s verbosity in some situations. The type argument between the angular brackets should be omitted if the compiler can infer it.
Since the diamond operator was only introduced in Java 7, this rule is automatically disabled when the project’s sonar.java.source is lower than 7.
There’s no point in having a public member in a non-public class because objects that can’t access the class will never have the chance to access the member.
This rule raises an issue when classes has methods, fields, or inner classes with higher visibility than the class itself has.
The Object.wait(…), Object.notify() and Object.notifyAll() methods are used in multithreaded environments to coordinate interdependent tasks that are performed by different threads. These methods are not thread-safe and by contract, they require the invoking Thread to own the object’s monitor. If a thread invokes one of these methods without owning the object’s monitor an IllegalMonitorStateException is thrown.
Instances of a Serializable class can be saved out to file and rehydrated at leisure. But that only works when all the values in the class instance are themselves Serializable (or transient). Storing a non-serializable value in a Serializable class will prevent the serialization of that class.
In Java 15 Text Blocks are official and can be used just like an ordinary String. However, when they are used to represent a big chunk of text, they should not be used directly in complex expressions, as it decreases the readability. In this case, it is better to extract the text block into a variable or a field.
This rule reports an issue when a text block longer than a number of lines given as a parameter is directly used within a lambda expression.
Double-checked locking can be used for lazy initialization of volatile fields, but only if field assignment is the last step in the synchronized block. Otherwise you run the risk of threads accessing a half-initialized object.
According to the documentation,
A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization…
This is because value-based classes are intended to be wrappers for value types, which will be primitive-like collections of data (similar to \`structs in other languages) that will come in future versions of Java.
Instances of a value-based class …
do not have accessible constructors, but are instead instantiated through factory methods which make no commitment as to the identity of returned instances;
This means that you can’t be sure you’re the only one trying to lock on any given instance of a value-based class, opening your code up to contention and deadlock issues.
Under Java 8 breaking this rule may not actually break your code, but there are no guarantees of the behavior beyond that.
This rule raises an issue when a known value-based class is used for synchronization. That includes all the classes in the java.time package except Clock; the date classes for alternate calendars, HijrahDate, JapaneseDate, MinguoDate, ThaiBuddhistDate; and the optional classes: Optional, OptionalDouble, OptionalLong, OptionalInt.
Note that this rule is automatically disabled when the project’s sonar.java.source is lower than 8\`.
Callers of a Boolean method may be expecting to receive true or false in response. But Boolean objects can take null as a possible value. Boolean methods should not return null unless the code is annotated appropriately. With the proper annotation, the caller is aware that the returned value could be null.
Non-encoded control characters and whitespace characters are often injected in the source code because of a bad manipulation. They are either invisible or difficult to recognize, which can result in bugs when the string is not what the developer expects. If you actually need to use a control character use their encoded version (ex: ASCII \`\n,\t,… or Unicode U+000D, U+0009,…).
This rule raises an issue when the following characters are seen in a literal string:
ASCII control character. (character index \< 32 or = 127)
Unicode whitespace characters.
Unicode C0 control characters
Unicode characters U+200B, U+200C, U+200D, U+2060, U+FEFF, U+2028, U+2029
No issue will be raised on the simple space character. Unicode U+0020\`, ASCII 32.
Serializing a non-\`static inner class will result in an attempt at serializing the outer class as well. If the outer class is actually serializable, then the serialization will succeed but possibly write out far more data than was intended.
Making the inner class static (i.e. "nested") avoids this problem, therefore inner classes should be static if possible. However, you should be aware that there are semantic differences between an inner class and a nested one:
an inner class can only be instantiated within the context of an instance of the outer class.
a nested (static\`) class can be instantiated independently of the outer class.
Classes without public static members cannot be used without being instantiated, but classes with only private constructors cannot be instantiated. When a class has only private constructors and no static members, it is useless and should be removed or refactored.
According to the specification:
Nonfinal \`static class fields are disallowed in EJBs because such fields make an enterprise bean difficult or impossible to distribute.
Therefore, all static fields in an EJB should also be final\`.
When directly subclassing \`java.io.OutputStream or java.io.FilterOutputStream, the only requirement is that you implement the method write(int). However most uses for such streams don’t write a single byte at a time and the default implementation for write(byte\[],int,int) will call write(int) for every single byte in the array which can create a lot of overhead and is utterly inefficient. It is therefore strongly recommended that subclasses provide an efficient implementation of write(byte\[],int,int).
This rule raises an issue when a direct subclass of java.io.OutputStream or java.io.FilterOutputStream doesn’t provide an override of write(byte\[],int,int)\`.
Specifying the default value for an annotation parameter is redundant. Such values should be omitted in the interests of readability.
\`Throwable.printStackTrace(...) prints a Throwable and its stack trace to some stream. By default that stream System.Err, which could inadvertently expose sensitive information.
Loggers should be used instead to print Throwables, as they have many advantages:
Users are able to easily retrieve the logs.
The format of log messages is uniform and allow users to browse the logs easily.
This rule raises an issue when printStackTrace\` is used without arguments, i.e. when the stack trace is printed to the default stream.
PreparedStatement is an object that represents a precompiled SQL statement, that can be used to execute the statement multiple times efficiently.
ResultSet is the Java representation of the result set of a database query obtained from a Statement object. A default ResultSet object is not updatable and has a cursor that moves forward only.
The parameters in PreparedStatement and ResultSet are indexed beginning at 1, not 0. When an invalid index is passed to the PreparedStatement or ResultSet methods, an IndexOutOfBoundsException is thrown. This can cause the program to crash or behave unexpectedly, leading to a poor user experience.
This rule raises an issue for the get methods in PreparedStatement and the set methods in ResultSet.
The problem with invoking \`Thread.start() in a constructor is that you’ll have a confusing mess on your hands if the class is ever extended because the superclass' constructor will start the thread before the child class has truly been initialized.
This rule raises an issue any time start is invoked in the constructor of a non-final\` class.
The Spring framework provides the annotation Async to mark a method (or all methods of a type) as a candidate for asynchronous execution.
Asynchronous methods do not necessarily, by their nature, return the result of their calculation immediately. Hence, it is unexpected and in clear breach of the Async contract for such methods to have a return type that is neither void nor a Future type.
Spring framework 4.3 introduced variants of the @RequestMapping annotation to better represent the semantics of the annotated methods. The use of @GetMapping, @PostMapping, @PutMapping, @PatchMapping and @DeleteMapping should be preferred to the use of the raw @RequestMapping(method = RequestMethod.XYZ).
Using toLowerCase() or toUpperCase() to make case insensitive comparisons is inefficient because it requires the creation of temporary, intermediate String objects.
Swing interfaces should be constructed and shown from the Swing event dispatch thread. Doing so from any other thread, such as from \`main risks deadlocks since you run the risk of multiple threads accessing things which are inherently not thread-safe.
Instead, use SwingUtilities.invokeLater or SwingUtilities.invokeAndWait to kick off a new Runnable\` that handles your GUI creation.
When creating a \`DateTimeFormatter using the WeekFields.weekBasedYear() temporal field, the resulting year number may be off by 1 at the beginning of a new year (when the date to format is in a week that is shared by two consecutive years).
Using this year number in combination with an incompatible week temporal field yields a result that may be confused with the first week of the previous year.
Instead, when paired with a week temporal field, the week-based year should only be used with the week of week-based year temporal field WeekFields.weekOfWeekBasedYear().
Alternatively the temporal field ChronoField.ALIGNED\_WEEK\_OF\_YEAR\` can be used together with a regular year (but not the week based year).
The use of escape sequences is mostly unnecessary in text blocks.
Spring Expression Language (SpEL) is an expression language used in the Spring Framework for evaluating and manipulating objects, properties, and conditions within Spring-based applications.
org.springframework.ui.Model is an interface in the Spring Framework that represents a container for data that can be passed between a controller and a view in a Spring MVC web application, allowing for data sharing during the request-response cycle.
Attributes added to the org.springframework.ui.Model should follow the Java identifier naming convention, which means they must start with a letter a-z, A-Z, underscore \_, or a dollar sign \$ and may be followed by letters, digits, underscores, or dollar signs.
Failure to do so may result in SpEL parsing errors when using these attributes in template engines.
Calling \`Class.newInstance invokes the class' default constructor. Unfortunately, since it’s not a direct call to the constructor, compile-time checking will be unable to detect the possibility. This means that your code will compile even if you haven’t put the invocation in a try block.
On the other hand, Construtor.newInstance handles exceptions by wrapping them in an InvocationTargetException and explicitly throwing them.
This rule raises an issue when Class.newInstance\` is used to invoke a constructor that throws checked exceptions.
Calling constructors for String, BigInteger, BigDecimal and the objects used to wrap primitives is less efficient and less clear than relying on autoboxing or valueOf.
Consider simplifying when possible for more efficient and cleaner code.
SpEL is used in Spring annotations and is parsed by the Spring framework, not by the Java compiler. This means that invalid SpEL expressions are not detected during Java compile time. They will cause exceptions during runtime instead, or even fail silently with the expression string interpreted as a simple string literal by Spring.
To ensure EJB portability, the EJB specification forbids the use of functionality in the \`java.io package. Instead of reading and writing files, EJB’s should use some other means of data storage and retrieval, such as JDBC.
This rule raises an issue for the first java.io\` method call in each method.
Importing a class statically allows you to use its public static members without qualifying them with the class name. That can be handy, but if you import too many classes statically, your code can become confusing and difficult to maintain.
Non-overridable methods (private or final) that don’t access instance data can be static to prevent any misunderstanding about the contract of the method.
Classes with only private constructors should be marked final to prevent any mistaken extension attempts.
Because a subclass instance may be cast to and treated as an instance of the superclass, overriding methods should uphold the aspects of the superclass contract that relate to the Liskov Substitution Principle. Specifically, if the parameters or return type of the superclass method are marked with any of the following: @Nullable, @CheckForNull, @NotNull, @NonNull, and @Nonnull, then subclass parameters are not allowed to tighten the contract, and return values are not allowed to loosen it.
Spring \`@Component, @Controller, @RestController,@Service, and @Repository classes are singletons by default, meaning only one instance of the class is ever instantiated in the application. Typically such a class might have a few static members, such as a logger, but all non-static members should be managed by Spring.
This rule raises an issue when a singleton @Component, @Controller, @RestController, @Service, or @Repository, not annotated with @ConfigurationProperties, has non-static members that are not annotated with one of:
org.springframework.beans.factory.annotation.Autowired
org.springframework.beans.factory.annotation.Value
javax.annotation.Inject
javax.annotation.Resource\`
Java 21 introduces the new Sequenced Collections API, which applies to all collections with a defined sequence on their elements, such as LinkedList, TreeSet, and others (see JEP 431). For projects using Java 21 and onwards, use this API instead of workaround implementations that were necessary before Java 21. One of the features of the new Sequenced Collections API is SequencedCollection.reversed() which returns a lightweight view of the original collection, in the reverse order.
This rule reports when reverse view would have been sufficient instead of a reverse copy of a sequenced collection created using a list constructor plus a Collections.reverse(collection); call.
If feasible, a view should be preferred over a copy because a view is a lightweight iterator without modification of the list itself.
Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all abstract class names match a provided regular expression. If a non-abstract class match the regular expression, an issue is raised to suggest to either make it abstract or to rename it.
While the Singleton pattern can be useful in certain situations, overusing it can have several drawbacks:
Tight coupling: The Singleton pattern can create tight coupling between the Singleton class and other classes that use it, making the code difficult to maintain and modify.
Global state: The Singleton pattern can create a global state, making it difficult to manage the state of the application and leading to unexpected behavior.
Testing: The Singleton pattern can make it difficult to test classes that depend on the Singleton, as the Singleton cannot be easily substituted with a mock object.
Scalability: The Singleton pattern can make it difficult to scale an application, as it can create a bottleneck if multiple threads try to access the Singleton concurrently.
Dependency injection: The Singleton pattern can make it difficult to use dependency injection frameworks, as the Singleton instance is usually created statically.
In general, the Singleton pattern should be used sparingly and only in situations where it provides a clear benefit over other patterns or approaches. It is important to consider the drawbacks and tradeoffs of using the Singleton pattern before incorporating it into an application.
Some API, like the AWS SDK, heavily rely on the builder pattern to create different data structures. Despite all the benefits, this pattern can become really verbose, especially when dealing with nested structures. In order to reach a more concise code, "Consumer Builders", also called "Consumer Interface" are often introduced.
The idea is to overload the methods taking others structures in a Builder with a Consumer of Builder instead. This enables to use a lambda instead of nesting another Builder, resulting in more concise and readable code.
This rule reports an issue when the Consumer Builder methods could be used instead of the classical ones.
Lambda expressions with only one argument with an inferred type (i.e., no explicit type declaration) can be written without parentheses around that single parameter. This syntax is simpler, more compact and readable than using parentheses and is therefore preferred.
This rule is automatically disabled when the project’s sonar.java.source is lower than 8, as lambda expressions were introduced in Java 8.
This rule raises an issue when a configured Java package or class is used.
The \`instanceof construction is a preferred way to check whether a variable can be cast to some type statically because a compile-time error will occur in case of incompatible types. The method isInstance() from java.lang.Class works differently and does type check at runtime only, incompatible types will therefore not be detected early in the development, potentially resulting in dead code. The isInstance() method should only be used in dynamic cases when the instanceof operator can’t be used.
This rule raises an issue when isInstance() is used and could be replaced with an instanceof\` check.
The Java language authors have been quite frank that \`Optional was intended for use only as a return type, as a way to convey that a method may or may not return a value.
And for that, it’s valuable but using Optional on the input side increases the work you have to do in the method without really increasing the value. With an Optional parameter, you go from having 2 possible inputs: null and not-null, to three: null, non-null-without-value, and non-null-with-value. Add to that the fact that overloading has long been available to convey that some parameters are optional, and there’s really no reason to have Optional parameters.
The rule also checks for Guava’s Optional, as it was the inspiration for the JDK Optional. Although it is different in some aspects (serialization, being recommended for use as collection elements), using it as a parameter type causes exactly the same problems as for JDK Optional\`.
The Java Collections framework defines interfaces such as java.util.List or java.util.Map. Several implementation classes are provided for each of those interfaces to fill different needs: some of the implementations guarantee a few given performance characteristics, some others ensure a given behavior, for example immutability.
Among the methods defined by the interfaces of the Collections framework, some are declared as "optional": an implementation class may choose to throw an UnsupportedOperationException when one of those methods is called. For example, java.util.Collections.emptyList() returns an implementation of java.util.List which is documented as "immutable". Calling the add method on this object triggers an UnsupportedOperationException.
This issue is raised when Sonar considers that a method is a 'Brain Method'. A Brain Method is a method that tends to centralize its owner’s class logic and generally performs too many operations. This can include checking too many conditions, using lots of variables, and ultimately making it difficult to understand, maintain and reuse. It is characterized by high LOC number, high cyclomatic and cognitive complexity, and a large number of variables being used.
Two "hash" classes, Hashtable, and ConcurrentHashMap offer contains methods. One might naively assume that the contains method searches both keys and values for its argument. And one would be wrong. Because these legacy methods search only values, they are likely to mislead maintainers even if the original coder understood precisely what’s going on.
It’s a common pattern to test the result of a \`java.util.Map.get() against null or calling java.util.Map.containsKey() before proceeding with adding or changing the value in the map. However the java.util.Map API offers a significantly better alternative in the form of the computeIfPresent() and computeIfAbsent() methods. Using these instead leads to cleaner and more readable code.
Note that this rule is automatically disabled when the project’s sonar.java.source\` is not 8.
When iterating over an Iterable with a for loop, the iteration variable could have the same type as the type returned by the iterator (the item type of the Iterable). This rule reports when a supertype of the item type is used for the variable instead, but the variable is then explicitly downcast in the loop body.
Using explicit type casts instead of leveraging the language’s type system is a bad practice. It disables static type checking by the compiler for the cast expressions, but potential errors will throw a ClassCastException during runtime instead.
In Java 21 the java.lang.Math class was updated with the static method Math.clamp, to clamp a numerical value between a min and a max value.
Using this built-in method is now the preferred way to restrict to a given interval, as it is more readable and less error-prone.
Class members that are not assigned a default value and are not initialized in a constructor will be set to null by the compiler. Even if code exists to properly set those members, there is a risk that they will be dereferenced before it is called, resulting in a NullPointerException.
Because you cannot guarantee that such classes will always be used properly, class members should always be initialized.
This rule flags members which have no default value and which are left uninitialized by at least one class constructor, but which are unconditionally dereferenced somewhere in the code.
Some method calls can effectively be "no-ops", meaning that the invoked method does nothing, based on the application’s configuration (eg: debug logs in production). However, even if the method effectively does nothing, its arguments may still need to evaluated before the method is called.
Passing message arguments that require further evaluation into a Guava com.google.common.base.Preconditions check can result in a performance penalty. That is because whether or not they’re needed, each argument must be resolved before the method is actually called.
Similarly, passing concatenated strings into a logging method can also incur a needless performance hit because the concatenation will be performed every time the method is called, whether or not the log level is low enough to show the message.
Instead, you should structure your code to pass static or pre-computed values into Preconditions conditions check and logging calls.
Specifically, the built-in string formatting should be used instead of string concatenation, and if the message is the result of a method call, then Preconditions should be skipped altogether, and the relevant exception should be conditionally thrown instead.
"equals" has a special place as a method name: it is expected to override boolean Object.equals(Object). Using the name for a method with some other signature is a recipe for confusion.
There’s no need to null test in conjunction with an instanceof test. null is not an instanceof anything, so a null check is redundant.
Before records appeared in Java 16, there was a common way to represent getters for private fields of a class: a method named "get" with a capitalized field name. For example, for a \`String field named "myField" the signature of the getter method will be: public String getMyField()
In records, getters are named differently. Getters created by default do not contain the "get" prefix. So for a record’s String field "myField" the getter method will be: public String myField()\`
This means that if you want to override the default getter behavior it is better to use the method provided by records instead of creating a new one. Otherwise, this will bring confusion to the users of the record as two getters will be available and even leads to bugs if the behavior is different from the default one.
This rule raises an issue when a record contains a getter named "get" with a capitalized field name that is not behaving the same as the default one.
Consistent naming of beans is important for the readability and maintainability of the code. More precisely, according to the Spring documentation:
Naming beans consistently makes your configuration easier to read and understand, and if you are using Spring AOP it helps a lot when applying advice to a set of beans related by name.
Not following accepted conventions can introduce inconsistent naming, especially when multiple developers work on the same project, leading to technical debt.
The spring documentation establishes a naming convention that consists of camel-cased names with a leading lowercase letter.
This rule raises an issue when a bean name defined in one of the following annotations does not adhere to the naming convention:
@Bean
@Configuration
@Controller
@Component
@Qualifier
@Repository
@Service
There is no need to declare the same dependency or plugin twice in a project. In fact, doing so is likely to cause errors in the future when maintainers try to change or upgrade the plugin or dependency.
Using checked exceptions forces method callers to deal with errors, either by propagating them or by handling them. Throwing exceptions makes them fully part of the API of the method.
But to keep the complexity for callers reasonable, methods should not throw more than one kind of checked exception.
A cast operation allows an object to be "converted" from one type to another. The compiler raises an error if it can determine that the target type is incompatible with the declared type of the object, otherwise it accepts the cast. However, depending on the actual runtime type of the object, a cast operation may fail at runtime. When a cast operation fails, a ClassCastException is thrown.
In Java, an enum is a special data type that allows you to define a set of constants. Nested enum types, also known as inner enum types, are enum types that are defined within another class or interface.
Nested enum types are implicitly static, so there is no need to declare them static explicitly.
JNI (Java Native Interface) code should be used only as a last resort, since part of the point of using Java is to make applications portable, and by definition the use of JNI can reduce portability.
Marking an array \`volatile means that the array itself will always be read fresh and never thread cached, but the items in the array will not be. Similarly, marking a mutable object field volatile means the object reference is volatile but the object itself is not, and other threads may not see updates to the object state.
This can be salvaged with arrays by using the relevant AtomicArray class, such as AtomicIntegerArray, instead. For mutable objects, the volatile\` should be removed, and some other method should be used to ensure thread-safety, such as synchronization, or ThreadLocal storage.
Collection classes from the \`java.util.concurrent package have their own concurrency control mechanisms. A concurrent collection is thread-safe, but not governed by a single exclusion lock, therefore using an instance of such a class for synchronization is, at best unnecessary and at worst likely to have unintended consequences.
This rule raises an issue when a synchronization lock is used on an instance of one of the collection classes from the java.util.concurrent\` package.
The Collection object returned by Map.entrySet(), Map.keySet() and Map.values(), and SequencedMap.sequencedEntrySet(), SequencedMap.sequencedKeySet() and SequencedMap.sequencedValues(), do not support the .add() and .addAll() methods, and they will throw an UnsupportedOperationException when invoked.
This rule raises an issue whenever .add() or .addAll() are invoked on collections that were retrieved this way.
Java’s `import mechanism allows the use of simple class names. Therefore, using a class' fully qualified name in a file that import`s the class is redundant and confusing.
The @Value annotation does not guarantee that the property is defined. Particularly if a field or parameter is annotated as nullable, it indicates that the developer assumes that the property may be undefined.
An undefined property may lead to runtime exceptions when the Spring framework tries to inject the autowired dependency during bean creation.
This rule raises an issue when a nullable field or parameter is annotated with @Value and no default value is provided.
An Iterable should not implement the Iterator interface or return this as an Iterator. The reason is that Iterator represents the iteration process itself, while Iterable represents the object we want to iterate over.
The Iterator instance encapsulates state information of the iteration process, such as the current and next element. Consequently, distinct iterations require distinct Iterator instances, for which Iterable provides the factory method Iterable.iterator().
This rule raises an issue when the Iterable.iterator() of a class implementing both Iterable and Iterator returns this.
Shadowing parent class static methods by creating methods in child classes with the same signatures can result in seemingly strange behavior if an instance of the child class is cast to the parent class and the static method is invoked using a reference to the child class. In such cases, the parent class' code will be executed instead of the code in the child class, confusing callers and potentially causing hard-to-find bugs. Instead the child class method should be renamed.
In Java 16 records represent a brief notation for immutable data structures. Records have autogenerated implementations for constructors with all parameters, getters, equals, hashcode and toString. Although these methods can still be overridden inside records, there is no use to do so if no special logic is required.
This rule reports an issue on empty compact constructors, trivial canonical constructors and simple getter methods with no additional logic.
The Advanced Encryption Standard (AES) encryption algorithm can be used with various modes. Some combinations are not secured:
Electronic Codebook (ECB) mode: Under a given key, any given plaintext block always gets encrypted to the same ciphertext block. Thus, it does not hide data patterns well. In some senses, it doesn’t provide serious message confidentiality, and it is not recommended for use in cryptographic protocols at all.
Cipher Block Chaining (CBC) with PKCS#5 padding (or PKCS#7) is susceptible to padding oracle attacks.
In both cases, Galois/Counter Mode (GCM) with no padding should be preferred.
This rule raises an issue when a Cipher instance is created with either ECB or CBC/PKCS5Padding mode.
Whether the valid value ranges for \`Date fields start with 0 or 1 varies by field. For instance, month starts at 0, and day of month starts at 1. Enter a date value that goes past the end of the valid range, and the date will roll without error or exception. For instance, enter 12 for month, and you’ll get January of the following year.
This rule checks for bad values used in conjunction with java.util.Date, java.sql.Date, and java.util.Calendar\`. Specifically, values outside of the valid ranges:
| Field | Valid |
|---|---|
month |
0-11 |
date (day) |
0-31 |
hour |
0-23 |
minute |
0-60 |
second |
0-61 |
Note that this rule does not check for invalid leap years, leap seconds (second = 61), or invalid uses of the 31st day of the month.
When the code under test in a unit test throws an exception, the test itself fails. Therefore, there is no need to surround the tested code with a \`try-catch structure to detect failure. Instead, you can simply move the exception type to the method signature.
This rule raises an issue when there is a fail assertion inside a catch\` block.
Supported frameworks:
JUnit3
JUnit4
JUnit5
Fest assert
AssertJ
When multiple tests differ only by a few hardcoded values they should be refactored as a single "parameterized" test. This reduces the chances of adding a bug and makes them more readable. Parameterized tests exist in most test frameworks (JUnit, TestNG, etc…).
The right balance needs of course to be found. There is no point in factorizing test methods when the parameterized version is a lot more complex than initial tests.
This rule raises an issue when at least 3 tests could be refactored as one parameterized test with less than 4 parameters. Only test methods which have at least one duplicated statement are considered.
The Collection.toArray() method returns an Object\[] when no arguments are provided to it. This can lead to a ClassCastException at runtime if you try to cast the returned array to an array of a specific type. Instead, use this method by providing an array of the desired type as the argument.
Note that passing a new T\[0] array of length zero as the argument is more efficient than a pre-sized array new T\[size].
The Java regex engine uses recursive method calls to implement backtracking. Therefore when a repetition inside a regular expression contains multiple paths (i.e. the body of the repetition contains an alternation (\`|), an optional element or another repetition), trying to match the regular expression can cause a stack overflow on large inputs. This does not happen when using a possessive quantifier (such as *+ instead of *) or when using a character class inside a repetition (e.g. \[ab]* instead of (a|b)*).
The size of the input required to overflow the stack depends on various factors, including of course the stack size of the JVM. One thing that significantly increases the size of the input that can be processed is if each iteration of the repetition goes through a chain of multiple constant characters because such consecutive characters will be matched by the regex engine without invoking any recursion.
For example, on a JVM with a stack size of 1MB, the regex (?:a|b)\* will overflow the stack after matching around 6000 characters (actual numbers may differ between JVM versions and even across multiple runs on the same JVM) whereas (?:abc|def)\* can handle around 15000 characters.
Since often times stack growth can’t easily be avoided, this rule will only report issues on regular expressions if they can cause a stack overflow on realistically sized inputs. You can adjust the maxStackConsumptionFactor\` parameter to adjust this.
2 ActionSupport is security-sensitive. For example, their use has led in the past to the following vulnerabilities:
All classes extending com.opensymphony.xwork2.ActionSupport are potentially remotely reachable. An action class extending ActionSupport will receive all HTTP parameters sent and these parameters will be automatically mapped to the setters of the Struts 2 action class. One should review the use of the fields set by the setters, to be sure they are used safely. By default, they should be considered as untrusted inputs.
This rule allows you to track the usage of the @SuppressWarnings mechanism.
Assuming that a comparator or compareTo method always returns -1 or 1 if the first operand is less than or greater than the second is incorrect.
The specifications for both methods, Comparator.compare and Comparable.compareTo, state that their return value is "a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object." Even if a specific comparator always returns -1, 0, or 1, this is only an implementation detail, not the API contract developers can rely on.
Correctly updating a \`static field from a non-static method is tricky to get right and could easily lead to bugs if there are multiple class instances and/or multiple threads in play. Ideally, static fields are only updated from synchronized static methods.
This rule raises an issue each time a static\` field is updated from a non-static method.
When an object is marked as static, it means that it belongs to the class rather than any class instance. This means there is only one copy of the static object in memory, regardless of how many class instances are created. Static objects are shared among all instances of the class and can be accessed using the class name rather than an instance of the class.
A data type is considered thread-safe if it can be used correctly by multiple threads, regardless of how those threads are executed, without requiring additional coordination from the calling code. In other words, a thread-safe data type can be accessed and modified by multiple threads simultaneously without causing any issues or requiring extra work from the programmer to ensure correct behavior.
Non-thread-safe objects are objects that are not designed to be used in a multi-threaded environment and can lead to race conditions and data inconsistencies when accessed by multiple threads simultaneously. Using them in a multi-threaded manner is highly likely to cause data problems or exceptions at runtime.
When a non-thread-safe object is marked as static in a multi-threaded environment, it can cause issues because the non-thread-safe object will be shared across different instances of the containing class.
This rule raises an issue when any of the following instances and their subtypes are marked as static:
java.util.Calendar,
java.text.DateFormat,
javax.xml.xpath.XPath, or
javax.xml.validation.SchemaFactory.
There is no requirement that class names be unique, only that they be unique within a package. Therefore trying to determine an object’s type based on its class name is an exercise fraught with danger. One of those dangers is that a malicious user will send objects of the same name as the trusted class and thereby gain trusted access.
Instead, the instanceof operator or the Class.isAssignableFrom() method should be used to check the object’s underlying type.
"A rose by any other name would smell as sweet," but main by any other name would not. Just because a method has the name "main", that doesn’t make it the entry point to an application. It must also have the correct signature. Specifically, it must be public static void and accept a single String \[] as an argument.
When the modulus of a negative number is calculated, the result will either be negative or zero. Thus, comparing the modulus of a variable for equality with a positive number (or a negative one) could result in unexpected results.
Disclosure of version information, usually overlooked by developers but disclosed by default by the systems and frameworks in use, can pose a significant security risk depending on the production environement.
Once this information is public, attackers can use it to identify potential security holes or vulnerabilities specific to that version.
Furthermore, if the published version information indicates the use of outdated or unsupported software, it becomes easier for attackers to exploit known vulnerabilities. They can search for published vulnerabilities related to that version and launch attacks that specifically target those vulnerabilities.
In object-oriented programming, inappropriately accessing static members of a base class via derived types is considered a code smell.
Static members are associated with the class itself, not with any specific instance of the class or its children classes. Accessing through the wrong type suggests a misunderstanding of the ownership and role of this member. This can make the maintenance of the code more complicated.
Therefore, the access should be done directly through the base class to maintain clarity and avoid potential misunderstandings.
Code is sometimes annotated as deprecated by developers maintaining libraries or APIs to indicate that the method, class, or other programming element is no longer recommended for use. This is typically due to the introduction of a newer or more effective alternative. For example, when a better solution has been identified, or when the existing code presents potential errors or security risks.
Deprecation is a good practice because it helps to phase out obsolete code in a controlled manner, without breaking existing software that may still depend on it. It is a way to warn other developers not to use the deprecated element in new code, and to replace it in existing code when possible.
Deprecated classes, interfaces, and their members should not be used, inherited or extended because they will eventually be removed. The deprecation period allows you to make a smooth transition away from the aging, soon-to-be-retired technology.
Check the documentation or the deprecation message to understand why the code was deprecated and what the recommended alternative is.
User enumeration refers to the ability to guess existing usernames in a web application database. This can happen, for example, when using "sign-in/sign-on/forgot password" functionalities of a website.
When an user tries to "sign-in" to a website with an incorrect username/login, the web application should not disclose that the username doesn’t exist with a message similar to "this username is incorrect", instead a generic message should be used like "bad credentials", this way it’s not possible to guess whether the username or password was incorrect during the authentication.
If a user-management feature discloses information about the existence of a username, attackers can use brute force attacks to retrieve a large amount of valid usernames that will impact the privacy of corresponding users and facilitate other attacks (phishing, password guessing etc …).
WebViews can be used to display web content as part of a mobile application. A browser engine is used to render and display the content. Like a web application, a mobile application that uses WebViews can be vulnerable to Cross-Site Scripting if untrusted code is rendered. In the context of a WebView, JavaScript code can exfiltrate local files that might be sensitive or even worse, access exposed functions of the application that can result in more severe vulnerabilities such as code injection. Thus JavaScript support should not be enabled for WebViews unless it is absolutely necessary and the authenticity of the web resources can be guaranteed.
This rule verifies that single-line comments are not located at the ends of lines of code. The main idea behind this rule is that in order to be really readable, trailing comments would have to be properly written and formatted (correct alignment, no interference with the visual structure of the code, not too long to be visible) but most often, automatic code formatters would not handle this correctly: the code would end up less readable. Comments are far better placed on the previous empty line of code, where they will always be visible and properly formatted.
While it is possible to access static members from a class instance, it’s bad form, and considered by most to be misleading because it implies to the readers of your code that there’s an instance of the member per class instance.
Hardcoding IP addresses is security-sensitive. It has led in the past to the following vulnerabilities:
Today’s services have an ever-changing architecture due to their scaling and redundancy needs. It is a mistake to think that a service will always have the same IP address. When it does change, the hardcoded IP will have to be modified too. This will have an impact on the product development, delivery, and deployment:
The developers will have to do a rapid fix every time this happens, instead of having an operation team change a configuration file.
It misleads to use the same address in every environment (dev, sys, qa, prod).
Last but not least it has an effect on application security. Attackers might be able to decompile the code and thereby discover a potentially sensitive address. They can perform a Denial of Service attack on the service, try to get access to the system, or try to spoof the IP address to bypass security checks. Such attacks can always be possible, but in the case of a hardcoded IP address solving the issue will take more time, which will increase an attack’s impact.
A cookie’s domain specifies which websites should be able to read it. Left blank, browsers are supposed to only send the cookie to sites that exactly match the sending domain. For example, if a cookie was set by lovely.dream.com, it should only be readable by that domain, and not by nightmare.com or even strange.dream.com. If you want to allow sub-domain access for a cookie, you can specify it by adding a dot in front of the cookie’s domain, like so: .dream.com. But cookie domains should always use at least two levels.
Cookie domains can be set either programmatically or via configuration. This rule raises an issue when any cookie domain is set with a single level, as in .com.
Developers often use TODO tags to mark areas in the code where additional work or improvements are needed but are not implemented immediately. However, these TODO tags sometimes get overlooked or forgotten, leading to incomplete or unfinished code. This rule aims to identify and address unattended TODO tags to ensure a clean and maintainable codebase. This description explores why this is a problem and how it can be fixed to improve the overall code quality.
Storing files locally is a common task for mobile applications. Files that are stored unencrypted can be read out and modified by an attacker with physical access to the device. Access to sensitive data can be harmful for the user of the application, for example when the device gets stolen.
Character classes in regular expressions are a convenient way to match one of several possible characters by listing the allowed characters or ranges of characters. If the same character is listed twice in the same character class or if the character class contains overlapping ranges, this has no effect.
Thus duplicate characters in a character class are either a simple oversight or a sign that a range in the character class matches more than is intended or that the author misunderstood how character classes work and wanted to match more than one character. A common example of the latter mistake is trying to use a range like \[0-99] to match numbers of up to two digits, when in fact it is equivalent to \[0-9]. Another common cause is forgetting to escape the - character, creating an unintended range that overlaps with other characters in the character class.
Nested code blocks create new scopes where variables declared within are inaccessible from the outside, and their lifespan ends with the block.
Although this may appear beneficial, their usage within a function often suggests that the function is overloaded. Thus, it may violate the Single Responsibility Principle, and the function needs to be broken down into smaller functions.
The presence of nested blocks that don’t affect the control flow might suggest possible mistakes in the code.
If an alternative in a regular expression only matches things that are already matched by another alternative, that alternative is redundant and serves no purpose.
In the best case this means that the offending subpattern is merely redundant and should be removed. In the worst case it’s a sign that this regex does not match what it was intended to match and should be reworked.
Shared naming conventions make it possible for a team to collaborate efficiently. Following the established convention of single-letter type parameter names helps users and maintainers of your code quickly see the difference between a type parameter and a poorly named class.
This rule check that all type parameter names match a provided regular expression. The following code snippets use the default regular expression.
A naming convention in software development is a set of guidelines for naming code elements like variables, functions, and classes.
The goal of a naming convention is to make the code more readable and understandable, which makes it easier to maintain and debug. It also ensures consistency in the code, especially when multiple developers are working on the same project.
This rule checks that field names match a provided regular expression.
This rule raises an issue when a \{visibility} \{operationName} is never referenced in the code.
There is no good excuse for an empty class. If it’s being used simply as a common extension point, it should be replaced with an interface. If it was stubbed in as a placeholder for future development it should be fleshed-out. In any other case, it should be eliminated.
In Unix file system permissions, the "`others`" category refers to all users except the owner of the file system resource and the members of the group assigned to this resource.
Granting permissions to this category can lead to unintended access to files or directories that could allow attackers to obtain sensitive information, disrupt services or elevate privileges.
There’s no point in forcing the overhead of a method call for a method that always returns the same constant value. Even worse, the fact that a method call must be made will likely mislead developers who call the method thinking that something more is done. Declare a constant instead.
This rule raises an issue if on methods that contain only one statement: the return of a constant value.
Empty statements represented by a semicolon ; are statements that do not perform any operation. They are often the result of a typo or a misunderstanding of the language syntax. It is a good practice to remove empty statements since they don’t add value and lead to confusion and errors.
Security through obscurity is no security at all, and the use of Base64 encoding to obscure a password will only slow an attacker down for seconds, at the most. Instead, passwords should be encrypted with private keys that are at least 128 bits in length.
This rule checks for the use of Base64 decoding on values that are then used in database and LDAP connections.
Having a variable with the same name in two unrelated classes is fine, but do the same thing within a class hierarchy and you’ll get confusion at best, chaos at worst.
When the execution is not explicitly terminated at the end of a switch case, it continues to execute the statements of the following case. While this is sometimes intentional, it often is a mistake which leads to unexpected behavior.
Testing for loop termination using an equality operator (== and !=) is dangerous, because it could set up an infinite loop. Using a broader relational operator instead casts a wider net, and makes it harder (but not impossible) to accidentally write an infinite loop.
Enabling runFinalizersOnExit is unsafe as it might result in erratic behavior and deadlocks on application exit.
Indeed, finalizers might be force-called on live objects while other threads are concurrently manipulating them.
Instead, if you want to execute something when the virtual machine begins its shutdown sequence, you should attach a shutdown hook.
Although they don’t affect the runtime behavior of the application after compilation, removing them will:
Improve the readability and maintainability of the code.
Help avoid potential naming conflicts.
Improve the build time, as the compiler has fewer lines to read and fewer types to resolve.
Reduce the number of items the code editor will show for auto-completion, thereby showing fewer irrelevant suggestions.
Files with no lines of code clutter a project and should be removed.
Cryptographic hash algorithms such as MD2, MD4, MD5, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160 and SHA-1 are no longer considered secure, because it is possible to have collisions (little computational effort is enough to find two or more different inputs that produce the same hash).
Ternary expressions, while concise, can often lead to code that is difficult to read and understand, especially when they are nested or complex. Prioritizing readability fosters maintainability and reduces the likelihood of bugs. Therefore, they should be removed in favor of more explicit control structures, such as if/else statements, to improve the clarity and readability of the code.
The \`catch block of a checked exception "E" may be hidden because the corresponding try block only throws exceptions derived from E.
These derived exceptions are handled in dedicated catch blocks prior to the catch block of the base exception E.
The catch\` block of E is unreachable and should be considered dead code. It should be removed, or the entire try-catch structure should be refactored.
It is also possible that a single exception type in a multi-catch block may be hidden while the catch block itself is still reachable. In that case it is enough to only remove the hidden exception type or to replace it with another type.
Possessive quantifiers in Regex patterns like below improve performance by eliminating needless backtracking:
?+ , \*+ , ++ , \{n}+ , \{n,}+ , \{n,m}+
But because possessive quantifiers do not keep backtracking positions and never give back, the following sub-patterns should not match only similar characters. Otherwise, possessive quantifiers consume all characters that could have matched the following sub-patterns and nothing remains for the following sub-patterns.
Libraries used to unarchive a file (zip, bzip2, tar, …) do what they were made for: they extract the content of the archive blindly, creating on the filesystem directories and files corresponding exactly to the content of the archive. Using a specially crafted archive containing some path traversal filenames, it is possible to create directories/files outside of the dir where the archive is extracted. This can lead to overwriting an executable or a configuration file with a file containing malicious code and transform a simple archive into a way to execute arbitrary code.
There are several reasons to use a group in a regular expression:
to change the precedence (e.g. do(g|or) will match 'dog' and 'door')
to remember parenthesised part of the match in the case of capturing group
to improve readability
In any case, having an empty group is most probably a mistake. Either it is a leftover after refactoring and should be removed, or the actual parentheses were intended and were not escaped.
The use of a non-standard algorithm is dangerous because a determined attacker may be able to break the algorithm and compromise whatever data has been protected. Standard algorithms like \`SHA-256, SHA-384, SHA-512, … should be used instead.
This rule tracks creation of java.security.MessageDigest\` subclasses.
The requirement for a final default clause is defensive programming. The clause should either take appropriate action, or contain a suitable comment as to why no action is taken.
There are valid cases for passing a variable multiple times into the same method call, but usually doing so is a mistake, and something else was intended for one of the arguments.
In Android applications, broadcasting intents is security-sensitive. For example, it has led in the past to the following vulnerability:
By default, broadcasted intents are visible to every application, exposing all sensitive information they contain.
This rule raises an issue when an intent is broadcasted without specifying any "receiver permission".
Android KeyStore is a secure container for storing key materials, in particular it prevents key materials extraction, i.e. when the application process is compromised, the attacker cannot extract keys but may still be able to use them. It’s possible to enable an Android security feature, user authentication, to restrict usage of keys to only authenticated users. The lock screen has to be unlocked with defined credentials (pattern/PIN/password, biometric).
By default XML processors attempt to load all XML schemas and DTD (their locations are defined with xsi:schemaLocation attributes and DOCTYPE declarations), potentially from an external storage such as file system or network, which may lead, if no restrictions are put in place, to server-side request forgery (SSRF) vulnerabilities.
Content security policy (CSP) (fetch directives) is a W3C standard which is used by a server to specify, via a http header, the origins from where the browser is allowed to load resources. It can help to mitigate the risk of cross site scripting (XSS) attacks and reduce privileges used by an application. If the website doesn’t define CSP header the browser will apply same-origin policy by default.
Content-Security-Policy: default-src 'self'; script-src ‘self ‘ [http://www.example.com](http://www.example.com)
In the above example, all resources are allowed from the website where this header is set and script resources fetched from example.com are also authorized:
\\ \ \ \