JDK-8075331 : jdb eval java.util.Arrays.asList(array) shows inconsistent behaviour
  • Type: Bug
  • Component: hotspot
  • Sub-Component: svc
  • Affected Version: 8u40
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-03-17
  • Updated: 2015-09-29
  • Resolved: 2015-04-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 JDK 8 JDK 9
6u105Fixed 7u91Fixed 8u60Fixed 9 b64Fixed
Description
Using jdb to evaluate 'java.util.Arrays.asList(array)' shows inconsistent behaviour.

(1) Java runtime says:
Arrays.asList(array) : [testArrays$1@cac736f, testArrays$2@5e265ba4]
Arrays.asList(array).size() : 2

(2) Jdb says:
eval java.util.Arrays.asList(array);
 java.util.Arrays.asList(array); = "[[Ljava.awt.event.MouseListener;@156643d4]"
eval java.util.Arrays.asList(array).size();
 java.util.Arrays.asList(array).size(); = 1

TO REPRODUCE:

(1) src
-------
% more testArrays.java
import java.awt.event.MouseAdapter;
import java.util.Arrays;
import java.util.List;

public class testArrays {

  public static void main(String[] args) {
    MouseAdapter mouseAdapter1 = new MouseAdapter(){};
    MouseAdapter mouseAdapter2 = new MouseAdapter(){};
    MouseAdapter[] array = new MouseAdapter[]{mouseAdapter1, mouseAdapter2};
    List<MouseAdapter> list = Arrays.asList(array);
    System.out.println("list : " + list);
    System.out.println("list.size() : " + list.size());
    System.out.println("Arrays.asList(array) : " + Arrays.asList(array));
    System.out.println("Arrays.asList(array).size() : " +
Arrays.asList(array).size());
// breakpoint here, evaluate Arrays.asList(array).size()

  }
}


(2) compile and run
-------------------
% /jdk1.8.0_40/bin/javac -g testArrays.java
% /jdk1.8.0_40/bin/java testArrays
list : [testArrays$1@15db9742, testArrays$2@6d06d69c]
list.size() : 2
Arrays.asList(array) : [testArrays$1@15db9742, testArrays$2@6d06d69c]
Arrays.asList(array).size() : 2
%


(3) debug
---------
% /jdk1.8.0_40/bin/jdb testArrays
Initializing jdb ...
> stop at testArrays:16
Deferring breakpoint testArrays:16.
It will be set after the class is loaded.
> run
run testArrays
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
>
VM Started: Set deferred breakpoint testArrays:16
list : [testArrays$1@cac736f, testArrays$2@5e265ba4]
list.size() : 2
Arrays.asList(array) : [testArrays$1@cac736f, testArrays$2@5e265ba4]

Breakpoint hit: "thread=main", testArrays.main(), line=16 bci=120
16        System.out.println("Arrays.asList(array).size() : " +
Arrays.asList(array).size());

main[1] eval list
 list = "[testArrays$1@cac736f, testArrays$2@5e265ba4]"
main[1] eval list.size()
 list.size() = 2
main[1] eval java.util.Arrays.asList(array)
 java.util.Arrays.asList(array) =
"[[Ljava.awt.event.MouseListener;@156643d4]"
main[1]  eval java.util.Arrays.asList(array).size()
 java.util.Arrays.asList(array).size() = 1
main[1] exit
Arrays.asList(array).size() : 2
%


Workaround
----------
The following code works as expected:

substitute the following lines
 MouseListener[] array = new MouseListener[]{mouseAdapter1, mouseAdapter2};
 List<MouseListener> list = Arrays.asList(array);
by
 MouseAdapter[] array = new MouseAdapter[]{mouseAdapter1, mouseAdapter2};
 List<MouseAdapter> list = Arrays.asList(array);
Comments
Here is a proposed patch for fixing this: diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java @@ -131,6 +131,15 @@ } @Override + boolean isAssignableTo(ReferenceType type) { + if (type.name().equals("java.lang.Object")) { + // interfaces are always assignable to j.l.Object + return true; + } + return super.isAssignableTo(type); + } + + @Override List<InterfaceType> interfaces() { return superinterfaces(); }
08-04-2015

reproducer attached
06-04-2015