Change this instance-reference to a static reference. Open
this.logger = logger;
- Read upRead up
- Exclude checks
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.
Noncompliant Code Example
public class A { public static int counter = 0; } public class B { private A first = new A(); private A second = new A(); public void runUpTheCount() { first.counter ++; // Noncompliant second.counter ++; // Noncompliant. A.counter is now 2, which is perhaps contrary to expectations } }
Compliant Solution
public class A { public static int counter = 0; } public class B { private A first = new A(); private A second = new A(); public void runUpTheCount() { A.counter ++; // Compliant A.counter ++; // Compliant } }
Remove this assignment of "logger". Open
this.logger = logger;
- Read upRead up
- Exclude checks
Assigning a value to a static
field in a constructor could cause unreliable behavior at runtime since it will change the value for all
instances of the class.
Instead remove the field's static
modifier, or initialize it statically.
Noncompliant Code Example
public class Person { static Date dateOfBirth; static int expectedFingers; public Person(date birthday) { dateOfBirth = birthday; // Noncompliant; now everyone has this birthday expectedFingers = 10; // Noncompliant } }
Compliant Solution
public class Person { Date dateOfBirth; static int expectedFingers = 10; public Person(date birthday) { dateOfBirth = birthday; } }
Extract this nested try block into a separate method. Open
try {
- Read upRead up
- Exclude checks
Nesting try
/catch
blocks severely impacts the readability of source code because it makes it too difficult to understand
which block will catch which exception.
%n should be used in place of \n to produce the platform-specific line separator. Open
logger.log(String.format(
"Failed to get the value of [%s] from the JSON file.\n\tError was: %s",
pathToRead,
e.getMessage()));
- Read upRead up
- Exclude checks
Because printf
-style format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that
result in the wrong strings being created. This rule statically validates the correlation of printf
-style format strings to their
arguments 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.
Noncompliant Code Example
String.format("First {0} and then {1}", "foo", "bar"); //Noncompliant. Looks like there is a confusion with the use of {{java.text.MessageFormat}}, parameters "foo" and "bar" will be simply ignored here String.format("Display %3$d and then %d", 1, 2, 3); //Noncompliant; the second argument '2' is unused String.format("Too many arguments %d and %d", 1, 2, 3); //Noncompliant; the third argument '3' is unused String.format("First Line\n"); //Noncompliant; %n should be used in place of \n to produce the platform-specific line separator String.format("Is myObject null ? %b", myObject); //Noncompliant; when a non-boolean argument is formatted with %b, it prints true for any nonnull value, and false for null. Even if intended, this is misleading. It's better to directly inject the boolean value (myObject == null in this case) String.format("value is " + value); // Noncompliant String s = String.format("string without arguments"); // Noncompliant MessageFormat.format("Result '{0}'.", value); // Noncompliant; String contains no format specifiers. (quote are discarding format specifiers) MessageFormat.format("Result {0}.", value, value); // Noncompliant; 2nd argument is not used MessageFormat.format("Result {0}.", myObject.toString()); // Noncompliant; no need to call toString() on objects java.util.Logger logger; logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject.toString()); // Noncompliant; no need to call toString() on objects logger.log(java.util.logging.Level.SEVERE, "Result.", new Exception()); // compliant, parameter is an exception logger.log(java.util.logging.Level.SEVERE, "Result '{0}'", 14); // Noncompliant - String contains no format specifiers. logger.log(java.util.logging.Level.SEVERE, "Result " + param, exception); // Noncompliant; Lambda should be used to differ string concatenation. org.slf4j.Logger slf4jLog; org.slf4j.Marker marker; slf4jLog.debug(marker, "message {}"); slf4jLog.debug(marker, "message", 1); // Noncompliant - String contains no format specifiers. org.apache.logging.log4j.Logger log4jLog; log4jLog.debug("message", 1); // Noncompliant - String contains no format specifiers.
Compliant Solution
String.format("First %s and then %s", "foo", "bar"); String.format("Display %2$d and then %d", 1, 3); String.format("Too many arguments %d %d", 1, 2); String.format("First Line%n"); String.format("Is myObject null ? %b", myObject == null); String.format("value is %d", value); String s = "string without arguments"; MessageFormat.format("Result {0}.", value); MessageFormat.format("Result '{0}' = {0}", value); MessageFormat.format("Result {0}.", myObject); java.util.Logger logger; logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject); logger.log(java.util.logging.Level.SEVERE, "Result {0}'", 14); logger.log(java.util.logging.Level.SEVERE, exception, () -> "Result " + param); org.slf4j.Logger slf4jLog; org.slf4j.Marker marker; slf4jLog.debug(marker, "message {}"); slf4jLog.debug(marker, "message {}", 1); org.apache.logging.log4j.Logger log4jLog; log4jLog.debug("message {}", 1);
See
- CERT, FIO47-C. - Use valid format strings
Catch Exception instead of Throwable. Open
} catch (Throwable e) {
- Read upRead up
- Exclude checks
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.
Noncompliant Code Example
try { /* ... */ } catch (Throwable t) { /* ... */ } try { /* ... */ } catch (Error e) { /* ... */ }
Compliant Solution
try { /* ... */ } catch (RuntimeException e) { /* ... */ } try { /* ... */ } catch (MyException e) { /* ... */ }
See
- MITRE, CWE-396 - Declaration of Catch for Generic Exception
- C++ Core Guidelines E.14 - Use purpose-designed user-defined types as exceptions (not built-in types)
Catch Exception instead of Throwable. Open
} catch (Throwable e) {
- Read upRead up
- Exclude checks
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.
Noncompliant Code Example
try { /* ... */ } catch (Throwable t) { /* ... */ } try { /* ... */ } catch (Error e) { /* ... */ }
Compliant Solution
try { /* ... */ } catch (RuntimeException e) { /* ... */ } try { /* ... */ } catch (MyException e) { /* ... */ }
See
- MITRE, CWE-396 - Declaration of Catch for Generic Exception
- C++ Core Guidelines E.14 - Use purpose-designed user-defined types as exceptions (not built-in types)
Either re-interrupt this method or rethrow the "InterruptedException" that can be caught here. Open
} catch (InterruptedException e) {
- Read upRead up
- Exclude checks
InterruptedExceptions
should never be ignored in the code, and simply logging the exception counts in this case as "ignoring". The
throwing of the InterruptedException
clears the interrupted state of the Thread, so if the exception is not handled properly the fact
that the thread was interrupted will be lost. Instead, InterruptedExceptions
should either be rethrown - immediately or after cleaning up
the method's state - or the thread should be re-interrupted by calling Thread.interrupt()
even if this is supposed to be a
single-threaded application. Any other course of action risks delaying thread shutdown and loses the information that the thread was interrupted -
probably without finishing its task.
Similarly, the ThreadDeath
exception should also be propagated. According to its JavaDoc:
If
ThreadDeath
is caught by a method, it is important that it be rethrown so that the thread actually dies.
Noncompliant Code Example
public void run () { try { while (true) { // do stuff } }catch (InterruptedException e) { // Noncompliant; logging is not enough LOGGER.log(Level.WARN, "Interrupted!", e); } }
Compliant Solution
public void run () { try { while (true) { // do stuff } }catch (InterruptedException e) { LOGGER.log(Level.WARN, "Interrupted!", e); // Restore interrupted state... Thread.currentThread().interrupt(); } }
See
- MITRE, CWE-391 - Unchecked Error Condition
- Dealing with InterruptedException