diff --git a/.config/pmd/java/ruleset.xml b/.config/pmd/java/ruleset.xml index c72b66a..341cb3a 100644 --- a/.config/pmd/java/ruleset.xml +++ b/.config/pmd/java/ruleset.xml @@ -10,6 +10,9 @@ + + + @@ -25,6 +28,7 @@ + @@ -207,14 +211,14 @@ message="StringBuilder/StringBuffer should not be used" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Usually all cases where `StringBuilder` (or the outdated `StringBuffer`) is used are either due to confusing (legacy) logic or may be replaced by a simpler string concatenation. - - Solution: - * Do not use `StringBuffer` because it's thread-safe and usually this is not needed - * If `StringBuilder` is only used in a simple method (like `toString`) and is effectively inlined: Use a simpler string concatenation (`"a" + x + "b"`). This will be optimized by the Java compiler internally. - * In all other cases: - * Check what is happening and if it makes ANY sense! If for example a CSV file is built here consider using a proper library instead! - * Abstract the Strings into a DTO, join them together using a collection (or `StringJoiner`) or use Java's Streaming API instead +Usually all cases where `StringBuilder` (or the outdated `StringBuffer`) is used are either due to confusing (legacy) logic or may be replaced by a simpler string concatenation. + +Solution: +* Do not use `StringBuffer` because it's thread-safe and usually this is not needed +* If `StringBuilder` is only used in a simple method (like `toString`) and is effectively inlined: Use a simpler string concatenation (`"a" + x + "b"`). This will be optimized by the Java compiler internally. +* In all other cases: + * Check what is happening and if it makes ANY sense! If for example a CSV file is built here consider using a proper library instead! + * Abstract the Strings into a DTO, join them together using a collection (or `StringJoiner`) or use Java's Streaming API instead 3 @@ -233,11 +237,11 @@ message="Setters of java.lang.System should not be called unless really needed" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Calling setters of java.lang.System usually indicates bad design and likely causes unexpected behavior. - For example, it may break when multiple Threads are setting the value. - It may also overwrite user defined options or properties. +Calling setters of java.lang.System usually indicates bad design and likely causes unexpected behavior. +For example, it may break when multiple Threads are setting the value. +It may also overwrite user defined options or properties. - Try to pass the value only to the place where it's really needed and use it there accordingly. +Try to pass the value only to the place where it's really needed and use it there accordingly. 3 @@ -256,10 +260,10 @@ message="Avoid @PostConstruct" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Using a `@PostConstruct` method is usually only done when field injection is used and initialization needs to be performed after that. +Using a `@PostConstruct` method is usually only done when field injection is used and initialization needs to be performed after that. - It's better to do this directly in the constructor with constructor injection, so that all logic will be encapsulated there. - This also makes using the bean in environments where JavaEE is not present - for example in tests - a lot easier, as forgetting to call the `@PostConstruct` method is no longer possible. +It's better to do this directly in the constructor with constructor injection, so that all logic will be encapsulated there. +This also makes using the bean in environments where JavaEE is not present - for example in tests - a lot easier, as forgetting to call the `@PostConstruct` method is no longer possible. 3 @@ -278,9 +282,9 @@ message="Avoid @PreDestroy" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - `@PreDestroy` should be replaced by implementing `AutoCloseable` and overwriting the `close` method instead. +`@PreDestroy` should be replaced by implementing `AutoCloseable` and overwriting the `close` method instead. - This also makes using the bean in environments where JavaEE is not present - for example in tests - a lot easier, as forgetting to call the `@PreDestroy` method is no much more difficult. +This also makes using the bean in environments where JavaEE is not present - for example in tests - a lot easier, as forgetting to call the `@PreDestroy` method is no much more difficult. 3 @@ -299,10 +303,10 @@ message="Avoid unmanaged threads" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Trying to manually manage threads usually gets quickly out of control and may result in various problems like uncontrollable spawning of threads. - Threads can also not be cancelled properly. +Trying to manually manage threads usually gets quickly out of control and may result in various problems like uncontrollable spawning of threads. +Threads can also not be cancelled properly. - Use managed Thread services like `ExecutorService` and `CompletableFuture` instead. +Use managed Thread services like `ExecutorService` and `CompletableFuture` instead. 3 @@ -321,10 +325,10 @@ message="ZipEntry name should be sanitized" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - ZipEntry name should be sanitized. - Unsanitized names may contain '..' which can result in path traversal ("ZipSlip"). +ZipEntry name should be sanitized. +Unsanitized names may contain '..' which can result in path traversal ("ZipSlip"). - You can suppress this warning when you properly sanitized the name. +You can suppress this warning when you properly sanitized the name. 4 @@ -343,12 +347,12 @@ message="Using Java Object (De-)Serialization is unsafe and has led to too many security vulnerabilities" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Nearly every known usage of (Java) Object Deserialization has resulted in [a security vulnerability](https://cloud.google.com/blog/topics/threat-intelligence/hunting-deserialization-exploits?hl=en). - Vulnerabilities are so common that there are [dedicated projects for exploit payload generation](https://github.com/frohoff/ysoserial). +Nearly every known usage of (Java) Object Deserialization has resulted in [a security vulnerability](https://cloud.google.com/blog/topics/threat-intelligence/hunting-deserialization-exploits?hl=en). +Vulnerabilities are so common that there are [dedicated projects for exploit payload generation](https://github.com/frohoff/ysoserial). - Java Object Serialization may also fail to deserialize when the underlying classes are changed. +Java Object Serialization may also fail to deserialize when the underlying classes are changed. - Use proven data interchange formats like JSON instead. +Use proven data interchange formats like JSON instead. 2 @@ -370,8 +374,8 @@ message="Unescaped native HTML is unsafe and will result in XSS vulnerabilities" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" > - Do not use native HTML! Use Vaadin layouts and components to create required structure. - If you are 100% sure that you escaped the value properly and you have no better options you can suppress this. +Do not use native HTML! Use Vaadin layouts and components to create required structure. +If you are 100% sure that you escaped the value properly and you have no better options you can suppress this. 2 @@ -395,9 +399,9 @@ message="Avoid using DecimalFormat or ChoiceFormat as field since it is thread-unsafe" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - java.text.NumberFormat: DecimalFormat and ChoiceFormat are thread-unsafe. +java.text.NumberFormat: DecimalFormat and ChoiceFormat are thread-unsafe. - Solution: Create a new local one when needed in a method. +Solution: Create a new local one when needed in a method. 1 @@ -427,11 +431,11 @@ public class Foo { message="Detected possible resource expensive implicit regex pattern compilation" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - A regular expression is compiled implicitly on every invocation. - Problem: This can be (CPU) expensive, depending on the length of the regular expression. +A regular expression is compiled implicitly on every invocation. +Problem: This can be (CPU) expensive, depending on the length of the regular expression. - Solution: Compile the regex pattern only once and assign it to a private static final Pattern field. - java.util.Pattern objects are thread-safe, so they can be shared among threads. +Solution: Compile the regex pattern only once and assign it to a private static final Pattern field. +java.util.Pattern objects are thread-safe, so they can be shared among threads. 2 @@ -476,11 +480,11 @@ String good_replaceInnerLineBreakBySpace() { message="Default buffer capacity is used which usually needs expensive expansions" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - The default constructor of ByteArrayOutputStream creates a 32 bytes initial capacity and for StringWriter 16 chars. - Such a small buffer as capacity usually needs several expensive expansions. +The default constructor of ByteArrayOutputStream creates a 32 bytes initial capacity and for StringWriter 16 chars. +Such a small buffer as capacity usually needs several expensive expansions. - Solution: Explicitly declared the buffer size so that an expansion is not needed in most cases. - Typically much larger than 32, e.g. 4096. +Solution: Explicitly declared the buffer size so that an expansion is not needed in most cases. +Typically much larger than 32, e.g. 4096. 2 @@ -516,12 +520,12 @@ class Good { message="Avoid re-streaming enum values to find a value by a field" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - The time to find element is O(n); n = the number of enum values. - This identical processing is executed for every call. - Considered problematic when `n > 3`. +The time to find element is O(n); n = the number of enum values. +This identical processing is executed for every call. +Considered problematic when `n > 3`. - Solution: Use a static field-to-enum-value Map. Access time is O(1), provided the hashCode is well-defined. - Implement a fromString method to provide the reverse conversion by using the map. +Solution: Use a static field-to-enum-value Map. Access time is O(1), provided the hashCode is well-defined. +Implement a fromString method to provide the reverse conversion by using the map. 3 @@ -582,11 +586,11 @@ public enum Fruit { message="Pattern.compile is used in a method. Compiling a regex pattern can be expensive, make it a static final field." class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - A regular expression is compiled on every invocation. - Problem: this can be expensive, depending on the length of the regular expression. +A regular expression is compiled on every invocation. +Problem: this can be expensive, depending on the length of the regular expression. - Solution: Usually a pattern is a literal, not dynamic and can be compiled only once. Assign it to a private static field. - java.util.Pattern objects are thread-safe so they can be shared among threads. +Solution: Usually a pattern is a literal, not dynamic and can be compiled only once. Assign it to a private static field. +java.util.Pattern objects are thread-safe so they can be shared among threads. 2 @@ -628,10 +632,10 @@ public static void good() { message="Avoid expensive recreation of DateTimeFormatter" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Recreating a DateTimeFormatter is relatively expensive. +Recreating a DateTimeFormatter is relatively expensive. - Solution: Java 8+ java.time.DateTimeFormatter is thread-safe and can be shared among threads. - Create the formatter from a pattern only once, to initialize a static final field. +Solution: Java 8+ java.time.DateTimeFormatter is thread-safe and can be shared among threads. +Create the formatter from a pattern only once, to initialize a static final field. 2 @@ -658,11 +662,11 @@ or pmd-java:matchesSig('java.time.format.DateTimeFormatterBuilder#toFormatter(_) message="Avoid expensive recreation of security providers" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Creating a security provider is expensive because of loading of algorithms and other classes. - Additionally, it uses synchronized which leads to lock contention when used with multiple threads. +Creating a security provider is expensive because of loading of algorithms and other classes. +Additionally, it uses synchronized which leads to lock contention when used with multiple threads. - Solution: This only needs to happen once in the JVM lifetime, because once loaded the provider is typically available from the Security class. - Create the security provider only once: Only in case when it's not yet available from the Security class. +Solution: This only needs to happen once in the JVM lifetime, because once loaded the provider is typically available from the Security class. +Create the security provider only once: Only in case when it's not yet available from the Security class. 2 @@ -709,9 +713,9 @@ class Foo { message="Expensive Reflection is used" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Reflection is relatively expensive. +Reflection is relatively expensive. - Solution: Avoid reflection. Use the non-reflective, explicit way like generation by IDE. +Solution: Avoid reflection. Use the non-reflective, explicit way like generation by IDE. 2 @@ -752,11 +756,11 @@ class Good { message="SimpleDateFormat is used. Since it is thread-unsafe, it needs expensive recreation." class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - java.util.SimpleDateFormat is thread-unsafe. - The usual solution is to create a new one when needed in a method. - Creating SimpleDateFormat is relatively expensive. +java.util.SimpleDateFormat is thread-unsafe. +The usual solution is to create a new one when needed in a method. +Creating SimpleDateFormat is relatively expensive. - Solution: Use java.time.DateTimeFormatter. These classes are immutable, thus thread-safe and can be made static. +Solution: Use java.time.DateTimeFormatter. These classes are immutable, thus thread-safe and can be made static. 2 @@ -793,15 +797,15 @@ public class Foo { message="Avoid the ForkJoinPool::commonPool used in parallelStream for blocking calls" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Blocking calls, for instance remote calls, may exhaust the common pool for some time thereby blocking all other use of the common pool. - In addition, nested use of the common pool can lead to deadlock. Do not use the common pool for blocking calls. - The parallelStream() call uses the common pool. +Blocking calls, for instance remote calls, may exhaust the common pool for some time thereby blocking all other use of the common pool. +In addition, nested use of the common pool can lead to deadlock. Do not use the common pool for blocking calls. +The parallelStream() call uses the common pool. - Solution: Use a dedicated thread pool with enough threads to get proper parallelism. - The number of threads in the common pool is equal to the number of CPUs and meant to utilize all of them. - It assumes CPU-intensive non-blocking processing of in-memory data. +Solution: Use a dedicated thread pool with enough threads to get proper parallelism. +The number of threads in the common pool is equal to the number of CPUs and meant to utilize all of them. +It assumes CPU-intensive non-blocking processing of in-memory data. - See also: [_Be Aware of ForkJoinPool#commonPool()_](https://dzone.com/articles/be-aware-of-forkjoinpoolcommonpool) +See also: [_Be Aware of ForkJoinPool#commonPool()_](https://dzone.com/articles/be-aware-of-forkjoinpoolcommonpool) 2 @@ -861,15 +865,15 @@ public class Foo { message="Avoid using the common thread pool, use a separate pool" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - CompletableFuture.supplyAsync/runAsync is typically used for remote calls. - By default it uses the common pool. - The number of threads in the common pool is equal to the number of CPU's, which is suitable for in-memory processing. - For I/O, however, this number is typically not suitable because most time is spent waiting for the response and not in CPU. - The common pool must not be used for blocking calls. +CompletableFuture.supplyAsync/runAsync is typically used for remote calls. +By default it uses the common pool. +The number of threads in the common pool is equal to the number of CPU's, which is suitable for in-memory processing. +For I/O, however, this number is typically not suitable because most time is spent waiting for the response and not in CPU. +The common pool must not be used for blocking calls. - Solution: A separate, properly sized pool of threads (an Executor) should be used for the async calls. +Solution: A separate, properly sized pool of threads (an Executor) should be used for the async calls. - See also: [_Be Aware of ForkJoinPool#commonPool()_](https://dzone.com/articles/be-aware-of-forkjoinpoolcommonpool) +See also: [_Be Aware of ForkJoinPool#commonPool()_](https://dzone.com/articles/be-aware-of-forkjoinpoolcommonpool) 2 @@ -907,9 +911,9 @@ public class Foo { message="Avoid CompletionService.take, use poll" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - `take()` stalls indefinitely in case of hanging threads and consumes a thread. +`take()` stalls indefinitely in case of hanging threads and consumes a thread. - Solution: use `poll()` with a timeout value and handle the timeout. +Solution: use `poll()` with a timeout value and handle the timeout. 2 @@ -943,9 +947,9 @@ public static void collectAllCollectionReplyFromThreads(CompletionService
  • - Stalls indefinitely in case of stalled Callable(s) and consumes threads. +Stalls indefinitely in case of stalled Callable(s) and consumes threads. - Solution: Provide a timeout to the invokeAll/invokeAny method and handle the timeout. +Solution: Provide a timeout to the invokeAll/invokeAny method and handle the timeout. 2 @@ -978,9 +982,9 @@ class Foo { message="Avoid future.get without timeout" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Stalls indefinitely in case of hanging threads and consumes a thread. +Stalls indefinitely in case of hanging threads and consumes a thread. - Solution: Provide a timeout value and handle the timeout. +Solution: Provide a timeout value and handle the timeout. 2 @@ -1011,10 +1015,10 @@ public static String good(CompletableFuture complFuture) throws Exceptio message="An HttpClient is created and combined with request-response" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Apache HttpClient with its connection pool and timeouts should be setup once and then used for many requests. - It is quite expensive to create and can only provide the benefits of pooling when reused in all requests for that connection. +Apache HttpClient with its connection pool and timeouts should be setup once and then used for many requests. +It is quite expensive to create and can only provide the benefits of pooling when reused in all requests for that connection. - Solution: Create/build HttpClient with proper connection pooling and timeouts once, and then use it for requests. +Solution: Create/build HttpClient with proper connection pooling and timeouts once, and then use it for requests. 3 @@ -1053,11 +1057,11 @@ class Foo { message="A Gson object is created for each method call, which is expensive." class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"> - Problem: Gson creation is relatively expensive. A JMH benchmark shows a 24x improvement reusing one instance. +Problem: Gson creation is relatively expensive. A JMH benchmark shows a 24x improvement reusing one instance. - Solution: Since Gson objects are thread-safe after creation, they can be shared between threads. - So reuse created instances from a static field. - Pay attention to use thread-safe (custom) adapters and serializers. +Solution: Since Gson objects are thread-safe after creation, they can be shared between threads. +So reuse created instances from a static field. +Pay attention to use thread-safe (custom) adapters and serializers. 3 diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index e975764..0e42c29 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -69,7 +69,7 @@ jobs: fi - name: Upload demo files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: demo-files-java-${{ matrix.java }} path: ${{ env.DEMO_MAVEN_MODULE }}/target/${{ env.DEMO_MAVEN_MODULE }}.jar @@ -152,7 +152,7 @@ jobs: - name: Upload report if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: pmd-report if-no-files-found: ignore diff --git a/bzst-dip-java-client/pom.xml b/bzst-dip-java-client/pom.xml index 26f97a1..7610e5a 100644 --- a/bzst-dip-java-client/pom.xml +++ b/bzst-dip-java-client/pom.xml @@ -514,7 +514,7 @@ com.puppycrawl.tools checkstyle - 12.1.0 + 12.1.1 diff --git a/pom.xml b/pom.xml index 656fdf0..0bb0d66 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ com.puppycrawl.tools checkstyle - 12.1.0 + 12.1.1