Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8193031: Collections.addAll is likely to perform worse than Collection.addAll #1764

Closed
wants to merge 10 commits into from
9 changes: 3 additions & 6 deletions src/java.base/share/classes/java/util/Collections.java
Expand Up @@ -5563,8 +5563,7 @@ public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
* Adds all of the specified elements to the specified collection.
* Elements to be added may be specified individually or as an array.
* The behavior of this convenience method is identical to that of
* {@code c.addAll(Arrays.asList(elements))}, but this method is likely
* to run significantly faster under most implementations.
* {@code c.addAll(Arrays.asList(elements))}.
*
* <p>When elements are specified individually, this method provides a
* convenient way to add a few elements to an existing collection:
Expand All @@ -5587,11 +5586,9 @@ public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
* @since 1.5
*/
@SafeVarargs
@SuppressWarnings("varargs")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need a SuppressWarnings here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, without this I get failed build:

Compiling 3057 files for java.base
Compiling 89 properties into resource bundles for java.desktop
/home/s.tsypanov/IdeaProjects/jdk-github/src/java.base/share/classes/java/util/Collections.java:5590: warning: [varargs] Varargs method could cause heap pollution from non-reifiable varargs parameter elements
        return c.addAll(Arrays.asList(elements));
                                      ^
error: warnings found and -Werror specified
1 error
1 warning
make[3]: *** [/home/s.tsypanov/IdeaProjects/jdk-github/build/linux-x86_64-server-release/jdk/modules/java.base/_the.java.base_batch] Error 1
CompileJavaModules.gmk:604: recipe for target '/home/s.tsypanov/IdeaProjects/jdk-github/build/linux-x86_64-server-release/jdk/modules/java.base/_the.java.base_batch' failed
make[2]: *** [java.base-java] Error 2
make[2]: *** Waiting for unfinished jobs....
make/Main.gmk:193: recipe for target 'java.base-java' failed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, it means there is a bug in the compiler, the analysis done for unsafe varargs (with -Xlint:varargs) doesn't check that the called method (here Arrays.asList()) is tagged with @SafeVarargs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I then wait for the fix of that bug to remove @SupressWarnings?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, the code is fine, for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've looked into com.sun.tools.javac.comp.Check and it seems the warning is produced here:

        @Override
        public void warn(LintCategory lint) {
            boolean warned = this.warned;
            super.warn(lint);
            if (warned) return; // suppress redundant diagnostics
            switch (lint) {
                case UNCHECKED:
                    Check.this.warnUnchecked(pos(), Warnings.ProbFoundReq(diags.fragment(uncheckedKey), found, expected));
                    break;
                case VARARGS:
                    if (method != null &&
                            method.attribute(syms.trustMeType.tsym) != null &&
                            isTrustMeAllowedOnMethod(method) &&
                            !types.isReifiable(method.type.getParameterTypes().last())) {
                        Check.this.warnUnsafeVararg(pos(), Warnings.VarargsUnsafeUseVarargsParam(method.params.last()));
                    }
                    break;
                default:
                    throw new AssertionError("Unexpected lint: " + lint);
            }
        }

Can we somehow read @SaveVarargs from signature of Arrays.asList() to avoid the warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@forax I've sent a mail into compiler-dev list: http://mail.openjdk.java.net/pipermail/compiler-dev/2020-December/015857.html

Let's see what they decide.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, despite the confusing (historical) name, syms.trustMeType is the SafeVarargs annotation. See Symtab.java, line 579.

public static <T> boolean addAll(Collection<? super T> c, T... elements) {
boolean result = false;
for (T element : elements)
result |= c.add(element);
return result;
return c.addAll(Arrays.asList(elements));
}

/**
Expand Down