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

Shenandoah: Crash with JFR and rapid class load and unload test

XMLWordPrintable

    • gc

      See the original report here:
       https://mail.openjdk.org/pipermail/shenandoah-dev/2025-February/025477.html

      Reproduces well with:

      $ build/linux-x86_64-server-fastdebug/images/jdk/bin/java -XX:+UseShenandoahGC -XX:StartFlightRecording=filename=100us.jfr -XX:+ShenandoahVerify -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGuaranteedGCInterval=1000 -Xlog:gc ClassUnloadTest.java

      #
      # A fatal error has been detected by the Java Runtime Environment:
      #
      # Internal Error (/home/shade/trunks/jdk/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp:110), pid=1616897, tid=1616904
      # Error: Before Updating References, Marked; Must be marked in complete bitmap

      Referenced from:
        interior location: 0x00000007fef6434c
        0x00000007fef64318 - klass 0x000073546e1baeb8 java.lang.Class
              allocated after mark start
          not after update watermark
              marked strong
              marked weak
          not in collection set
        mark: mark(is_unlocked hash=0x000000002a90b490 age=0)
        region: | 3833|R |Y|BTE 7fe800000, 7fef92328, 7ff000000|TAMS 7fef547a8|UWM 7fef92328|U 7752K|T 0B|G 7344K|S 407K|L 5919K|CP 0
        class: DynamicClass
          classloader: 0x000000079001cd00
          classloader after TAMS: false
          classloader marked: false

      Object:
        0x000000079001ce88 - klass 0x000073546e1c23c0 java.lang.Module
          not allocated after mark start
          not after update watermark
          not marked strong
          not marked weak
              in collection set
        mark: mark(is_unlocked no_hash age=0)
        region: | 3612|CS |Y|BTE 790000000, 790800000, 790800000|TAMS 790800000|UWM 790800000|U 8192K|T 8192K|G 0B|S 0B|L 20936B|CP 0
        module: unnamed module

      Forwardee:
        (the object itself)

      I have explored this a bit. It looks to me the DynamicClass gets its "module" from the classloader "unnamed module" oop. Looks like DynamicClass gets allocated after TAMS, and thus is treated as implicitly alive. For some reason the class/instance is treated as dead. (Hypothesis: the class is not on stack anymore, since we have left the method, but the object is already on heap.) Since the class is not reachable anymore, it somehow gets unloaded, and its classloader is marked dead. Since classloader is dead, we do not mark/evac its "unnamed module" oop either. So now we are in the situation where a "marked" Class object references the unmarked oop.

      Still not clear how JFR participates in this, but it might be related to JDK-8340364.

      Some debugging breadcrumbs here:
       https://github.com/openjdk/jdk/compare/master...shipilev:jdk:JDK-8350580-shenandoah-dynamic-class

            shade Aleksey Shipilev
            shade Aleksey Shipilev
            Votes:
            1 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated: