Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6851282

JIT miscompilation results in null entry in array when using CompressedOops

    Details

    • Subcomponent:
    • Resolved In Build:
      b07
    • CPU:
      x86, sparc
    • OS:
      linux, solaris_10, windows_2003
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.6.0_14"
        Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
        Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)

        java version "1.7.0-ea"
        Java(TM) SE Runtime Environment (build 1.7.0-ea-b59)
        Java HotSpot(TM) 64-Bit Server VM (build 16.0-b03, mixed mode)


        FULL OS VERSION :
        Linux mac 2.6.29.4-162.fc11.x86_64 #1 SMP Mon May 25 16:51:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

        A DESCRIPTION OF THE PROBLEM :
        When executing the included program, the array will contain null fields after the server JIT recompiles some of the methods even though that should be impossible.

        This only happens with -XX:+UseCompressedOops. I tested with JDK6u14 and the latest JDK7 snapshot (b59)

        THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

        THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run the included program with JDK6u14 -server -XX:+UseCompressedOops

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        Expected results: nothing gets printed to the console

        Actual results: The word "bug" is printed a few times.

        Note that the problem does not occur if -XX:+UseCompressedOops is not used.
        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        package test;

        import java.util.ArrayList;
        import java.util.List;


        public class Hs {
          void foo(A a, A[] as) {
            for (A a1 : as) {
              B[] filtered = a.c(a1);
              for (B b : filtered)
                if (b == null) {
                  System.out.println("bug");
                }
            }
          }
          
          public static void main(String[] args) {
            List<A> as = new ArrayList<A>();
            for (int i = 0; i < 5000; i++) {
              List<B> bs = new ArrayList<B>();
              for (int j = i; j < i + 1000; j++)
                bs.add(new B(j));
              as.add(new A(bs.toArray(new B[0])));
            }
            new Hs().foo(as.get(0), as.subList(1, as.size()).toArray(new A[0]));
          }
        }

        class A {
          final B[] bs;
          
          public A(B[] bs) {
            this.bs = bs;
          }
          
          final B[] c(final A a) {
            return new BoxedArray<B>(bs).filter(new Function<B, Boolean>() {
              public Boolean apply(B arg) {
                for (B b : a.bs) {
                  if (b.d == arg.d)
                    return true;
                }
                return false;
              }
            });
          }
        }

        class BoxedArray<T> {
          
          private final T[] array;
          
          BoxedArray(T[] array) {
            this.array = array;
          }
          
          public T[] filter(Function<T, Boolean> function) {
            boolean[] include = new boolean[array.length];
            int len = 0;
            int i = 0;
            while (i < array.length) {
              if (function.apply(array[i])) {
                include[i] = true;
                len += 1;
              }
              i += 1;
            }
            T[] result = (T[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), len);
            len = 0;
            i = 0;
            while (len < result.length) {
              if (include[i]) {
                result[len] = array[i];
                len += 1;
              }
              i += 1;
            }
            return result;
          }
        }

        interface Function<T, R> {
          R apply(T arg);
        }

        class B {
          final int d;
          public B(int d) {
            this.d = d;
          }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Remove -XX:+UseCompressedOops switch.

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  kvn Vladimir Kozlov
                  Reporter:
                  tbell Tim Bell
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  1 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:
                    Imported:
                    Indexed: