diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index eb1a123a63..c0719e98bb 100644
--- a/docs/pages/release_notes.md
+++ b/docs/pages/release_notes.md
@@ -252,6 +252,11 @@ The rule reference documentation has been updated to reflect these changes.
* The Java rule `EmptyCatchBlock` (category `errorprone`, former ruleset `java-empty`) has been changed to ignore
exceptions named `ignore` or `expected` by default. You can still override this behaviour by setting the `allowExceptionNameRegex` property.
+* The Java rule `OptimizableToArrayCall` (category `performance`, former ruleset `design`) has been
+ modified to fit for the current JVM implementations: It basically detects now the opposite and suggests to
+ use `Collection.toArray(new E[0])` with a zero-sized array.
+ See [Arrays of Wisdom of the Ancients](https://shipilev.net/blog/2016/arrays-wisdom-ancients/).
+
#### Deprecated Rules
* The Java rules `NcssConstructorCount`, `NcssMethodCount`, and `NcssTypeCount` (ruleset `java-codesize`) have been
@@ -339,6 +344,7 @@ a warning will now be produced suggesting users to adopt it for better performan
* cpp
* [#448](https://github.com/pmd/pmd/issues/448): \[cpp] Write custom CharStream to handle continuation characters
* java
+ * [#1454](https://sourceforge.net/p/pmd/bugs/1454/): \[java] OptimizableToArrayCall is outdated and invalid in current JVMs
* [#1513](https://sourceforge.net/p/pmd/bugs/1513/): \[java] Remove deprecated rule UseSingleton
* [#328](https://github.com/pmd/pmd/issues/328): \[java] java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/servlet/jsp/PageContext
* [#487](https://github.com/pmd/pmd/pull/487): \[java] Fix typeresolution for anonymous extending object
diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml
index 388f1d39ed..86adf370c9 100644
--- a/pmd-java/src/main/resources/category/java/performance.xml
+++ b/pmd-java/src/main/resources/category/java/performance.xml
@@ -428,9 +428,17 @@ public class Foo {
class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#optimizabletoarraycall">
-Calls to a collection's toArray() method should specify target arrays sized to match the size of the
-collection. Initial arrays that are too small are discarded in favour of new ones that have to be created
-that are the proper size.
+Calls to a collection's `toArray(E[])` method should specify a target array of zero size. This allows the JVM
+to optimize the memory allocation and copying as much as possible.
+
+Previous versions of this rule (pre PMD 6.0.0) suggested the opposite, but current JVM implementations
+perform always better, when they have full control over the target array. And allocation an array via
+reflection is nowadays as fast as the direct allocation.
+
+See also [Arrays of Wisdom of the Ancients](https://shipilev.net/blog/2016/arrays-wisdom-ancients/)
+
+Note: If you don't need an array of the correct type, then the simple `toArray()` method without an array
+is faster, but returns only an array of type `Object[]`.
3
@@ -442,7 +450,7 @@ that are the proper size.
[
PrimarySuffix/Arguments/ArgumentList/Expression
/PrimaryExpression/PrimaryPrefix/AllocationExpression
- /ArrayDimsAndInits/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image='0']
+ /ArrayDimsAndInits/Expression/PrimaryExpression/PrimaryPrefix[not(Literal[@Image='0'])]
]
]]>
@@ -450,13 +458,13 @@ PrimarySuffix/Arguments/ArgumentList/Expression
foos = getFoos();
- // inefficient, the array will be discarded
+// much better; this one allows the jvm to allocate an array of the correct size and effectively skip
+// the zeroing, since each array element will be overridden anyways
Foo[] fooArray = foos.toArray(new Foo[0]);
- // much better; this one sizes the destination array,
- // avoiding of a new one via reflection
+// inefficient, the array needs to be zeroed out by the jvm before it is handed over to the toArray method
Foo[] fooArray = foos.toArray(new Foo[foos.size()]);
]]>
diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/OptimizableToArrayCall.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/OptimizableToArrayCall.xml
index b58567951c..d4866c48b2 100644
--- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/OptimizableToArrayCall.xml
+++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/OptimizableToArrayCall.xml
@@ -4,10 +4,8 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
-
- 1
+ Preferred usage (sf #1454)
+ 0
-
- 0
+ Array dimensioner uses method call, performance issue
+ 1
-
- 0
+ Array dimensioner uses variable, performance issue
+ 1
#937 OptimizableToArrayCall does not catch multilevel method chains
- 1
+ 0
+
+
+
+ Array with a literal dimension, zero still better
+ 1
+
+
+
+
+ toArray call without an array should not be flagged
+ 0
+