JDK-8316342 : CLHSDB "dumpclass" command produces invalid classes
  • Type: Bug
  • Component: hotspot
  • Sub-Component: svc-agent
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2023-09-15
  • Updated: 2023-11-21
  • Resolved: 2023-11-14
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 22
22 b24Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
serviceability/sa/ClhsdbDumpclass.java test fails on all debug builds producing invalid classes.
https://bugs.openjdk.org/browse/JDK-8294969 "Convert jdk.jdeps javap to use the Classfile API" introduces more strict class checking.
serviceability/sa/ClhsdbDumpclass.java test log newly contains numerous errors where field instructions point to method type descriptors. The test fails when an error occurs in the log.
Affected are only debug builds of the JDK on all systems.

Sample of the errors from the log:
testoutput/test-support/jtreg_open_test_hotspot_jtreg_hotspot_serviceability/scratch/0/jdk/test/lib/apps/LingeredApp.class
  Last modified Sep 14, 2023; size 14188 bytes
  SHA-256 checksum d0c5e6fa04c17e5b457c48638b3f1b19ed8c3b309e991f153e0b68287d08d40b
  Compiled from "LingeredApp.java"
public class jdk.test.lib.apps.LingeredApp
  minor version: 0
  major version: 66
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #8                          // jdk/test/lib/apps/LingeredApp
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 16, methods: 39, attributes: 4
Constant pool:
    #1 = Methodref          #2.#3         // java/lang/Object."<init>":()V
    #2 = Class              #4            // java/lang/Object
    #3 = NameAndType        #5:#6         // "<init>":()V
    #4 = Utf8               java/lang/Object
    #5 = Utf8               <init>
    #6 = Utf8               ()V
    #7 = Fieldref           #8.#9         // jdk/test/lib/apps/LingeredApp.finishAppCalled:Z
    #8 = Class              #10           // jdk/test/lib/apps/LingeredApp
    #9 = NameAndType        #11:#12       // finishAppCalled:Z
   #10 = Utf8               jdk/test/lib/apps/LingeredApp
   #11 = Utf8               finishAppCalled
   #12 = Utf8               Z
   #13 = Fieldref           #8.#14        // jdk/test/lib/apps/LingeredApp.useDefaultClasspath:Z
   #14 = NameAndType        #15:#12       // useDefaultClasspath:Z
   #15 = Utf8               useDefaultClasspath
   #16 = Fieldref           #8.#17        // jdk/test/lib/apps/LingeredApp.forceCrash:Z
   #17 = NameAndType        #18:#12       // forceCrash:Z
   #18 = Utf8               forceCrash
   #19 = Fieldref           #8.#20        // jdk/test/lib/apps/LingeredApp.lockFileName:Ljava/lang/String;
   #20 = NameAndType        #21:#22       // lockFileName:Ljava/lang/String;
   #21 = Utf8               lockFileName
   #22 = Utf8               Ljava/lang/String;
   #23 = Methodref          #24.#25       // java/util/UUID.randomUUID:()Ljava/util/UUID;
   #24 = Class              #26           // java/util/UUID
   #25 = NameAndType        #27:#28       // randomUUID:()Ljava/util/UUID;
   #26 = Utf8               java/util/UUID
   #27 = Utf8               randomUUID
   #28 = Utf8               ()Ljava/util/UUID;
   #29 = Methodref          #24.#30       // java/util/UUID.toString:()Ljava/lang/String;
   #30 = NameAndType        #31:#32       // toString:()Ljava/lang/String;
   #31 = Utf8               toString
   #32 = Utf8               ()Ljava/lang/String;
   #33 = InvokeDynamic      #0:#34        // #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
   #34 = NameAndType        #35:#36       // makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
   #35 = Utf8               makeConcatWithConstants
   #36 = Utf8               (Ljava/lang/String;)Ljava/lang/String;
   #37 = Fieldref           #8.#38        // jdk/test/lib/apps/LingeredApp.logFileName:Ljava/lang/String;
   #38 = NameAndType        #39:#22       // logFileName:Ljava/lang/String;
   #39 = Utf8               logFileName
   #40 = Fieldref           #8.#41        // jdk/test/lib/apps/LingeredApp.appProcess:Ljava/lang/Process;
   #41 = NameAndType        #42:#43       // appProcess:Ljava/lang/Process;
   #42 = Utf8               appProcess
   #43 = Utf8               Ljava/lang/Process;
   #44 = Class              #45           // java/lang/RuntimeException
   #45 = Utf8               java/lang/RuntimeException
   #46 = String             #47           // Process is not alive
   #47 = Utf8               Process is not alive
   #48 = Methodref          #44.#49       // java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
   #49 = NameAndType        #5:#50        // "<init>":(Ljava/lang/String;)V
   #50 = Utf8               (Ljava/lang/String;)V
   #51 = Methodref          #52.#53       // java/lang/Process.pid:()J
   #52 = Class              #54           // java/lang/Process
   #53 = NameAndType        #55:#56       // pid:()J
   #54 = Utf8               java/lang/Process
   #55 = Utf8               pid
   #56 = Utf8               ()J
   #57 = Fieldref           #8.#58        // jdk/test/lib/apps/LingeredApp.stdoutBuffer:Ljava/io/ByteArrayOutputStream;
   #58 = NameAndType        #59:#60       // stdoutBuffer:Ljava/io/ByteArrayOutputStream;
   #59 = Utf8               stdoutBuffer
   #60 = Utf8               Ljava/io/ByteArrayOutputStream;
   #61 = Methodref          #62.#30       // java/io/ByteArrayOutputStream.toString:()Ljava/lang/String;
   #62 = Class              #63           // java/io/ByteArrayOutputStream
   #63 = Utf8               java/io/ByteArrayOutputStream
   #64 = Methodref          #52.#65       // java/lang/Process.isAlive:()Z
   #65 = NameAndType        #66:#67       // isAlive:()Z
   #66 = Utf8               isAlive
   #67 = Utf8               ()Z
   #68 = String             #69           // Process is still alive. Can\\'t get its output.
   #69 = Utf8               Process is still alive. Can\\'t get its output.
   #70 = Fieldref           #8.#71        // jdk/test/lib/apps/LingeredApp.output:Ljdk/test/lib/process/OutputBuffer;
   #71 = NameAndType        #72:#73       // output:Ljdk/test/lib/process/OutputBuffer;
   #72 = Utf8               output
   #73 = Utf8               Ljdk/test/lib/process/OutputBuffer;
   #74 = Fieldref           #8.#75        // jdk/test/lib/apps/LingeredApp.stderrBuffer:Ljava/io/ByteArrayOutputStream;
   #75 = NameAndType        #76:#60       // stderrBuffer:Ljava/io/ByteArrayOutputStream;
   #76 = Utf8               stderrBuffer
   #77 = Methodref          #52.#78       // java/lang/Process.exitValue:()I
   #78 = NameAndType        #79:#80       // exitValue:()I
   #79 = Utf8               exitValue
   #80 = Utf8               ()I
   #81 = InterfaceMethodref #82.#83       // jdk/test/lib/process/OutputBuffer.of:(Ljava/lang/String;Ljava/lang/String;I)Ljdk/test/lib/process/OutputBuffer;
   #82 = Class              #84           // jdk/test/lib/process/OutputBuffer
   #83 = NameAndType        #85:#86       // of:(Ljava/lang/String;Ljava/lang/String;I)Ljdk/test/lib/process/OutputBuffer;
   #84 = Utf8               jdk/test/lib/process/OutputBuffer
   #85 = Utf8               of
   #86 = Utf8               (Ljava/lang/String;Ljava/lang/String;I)Ljdk/test/lib/process/OutputBuffer;
   #87 = Methodref          #62.#3        // java/io/ByteArrayOutputStream."<init>":()V
   #88 = Class              #89           // jdk/test/lib/process/StreamPumper
   #89 = Utf8               jdk/test/lib/process/StreamPumper
   #90 = Methodref          #52.#91       // java/lang/Process.getInputStream:()Ljava/io/InputStream;
   #91 = NameAndType        #92:#93       // getInputStream:()Ljava/io/InputStream;
   #92 = Utf8               getInputStream
   #93 = Utf8               ()Ljava/io/InputStream;
   #94 = Methodref          #88.#95       // jdk/test/lib/process/StreamPumper."<init>":(Ljava/io/InputStream;Ljava/io/OutputStream;)V
   #95 = NameAndType        #5:#96        // "<init>":(Ljava/io/InputStream;Ljava/io/OutputStream;)V
   #96 = Utf8               (Ljava/io/InputStream;Ljava/io/OutputStream;)V
   #97 = Methodref          #52.#98       // java/lang/Process.getErrorStream:()Ljava/io/InputStream;
   #98 = NameAndType        #99:#93       // getErrorStream:()Ljava/io/InputStream;
   #99 = Utf8               getErrorStream
  #100 = Class              #101          // java/lang/Thread
  #101 = Utf8               java/lang/Thread
  #102 = Methodref          #100.#103     // java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
  #103 = NameAndType        #5:#104       // "<init>":(Ljava/lang/Runnable;)V
  #104 = Utf8               (Ljava/lang/Runnable;)V
  #105 = Fieldref           #8.#106       // jdk/test/lib/apps/LingeredApp.outPumperThread:Ljava/lang/Thread;
  #106 = NameAndType        #107:#108     // outPumperThread:Ljava/lang/Thread;
  #107 = Utf8               outPumperThread
  #108 = Utf8               Ljava/lang/Thread;
  #109 = Fieldref           #8.#110       // jdk/test/lib/apps/LingeredApp.errPumperThread:Ljava/lang/Thread;
  #110 = NameAndType        #111:#108     // errPumperThread:Ljava/lang/Thread;
  #111 = Utf8               errPumperThread
  #112 = Methodref          #100.#113     // java/lang/Thread.setDaemon:(Z)V
  #113 = NameAndType        #114:#115     // setDaemon:(Z)V
  #114 = Utf8               setDaemon
  #115 = Utf8               (Z)V
  #116 = Methodref          #100.#117     // java/lang/Thread.start:()V
  #117 = NameAndType        #118:#6       // start:()V
  #118 = Utf8               start

...

  public void printCommandLine(java.util.List<java.lang.String>);
    descriptor: (Ljava/util/List;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=5, locals=2, args_size=2
Error: Not a FieldRefEntry at index: 102
         0: getstatic     ???
         3: aload_1
         4: invokeinterface #291,  1          // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
         9: invokedynamic #295,  0            // InvokeDynamic #4:apply:()Ljava/util/function/Function;
        14: invokeinterface #299,  2          // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
        19: ldc_w         #305                // String
        22: ldc_w         #307                // String Command line: [
        25: ldc_w         #309                // String ]
        28: invokestatic  #311                // Method java/util/stream/Collectors.joining:(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/util/stream/Collector;
        31: invokeinterface #317,  2          // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
        36: checkcast     #125                // class java/lang/String
        39: invokevirtual #321                // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        42: return
      LineNumberTable:
        line 344: 0
        line 345: 14
        line 346: 28
        line 344: 39
        line 347: 42
    Signature: #576                         // (Ljava/util/List<Ljava/lang/String;>;)V

  public void deleteLock() throws java.io.IOException;
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
Error: Not a FieldRefEntry at index: 48
         1: getfield      ???
         4: iconst_0
         5: anewarray     #125                // class java/lang/String
         8: invokestatic  #127                // Method java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;
        11: astore_1
        12: aload_1
        13: invokestatic  #174                // Method java/nio/file/Files.delete:(Ljava/nio/file/Path;)V
        16: goto          20
        19: astore_1
        20: return
      Exception table:
         from    to  target type
             0    16    19   Class java/nio/file/NoSuchFileException
      StackMapTable: number_of_entries = 2
        frame_type = 83 /* same_locals_1_stack_item */
          stack = [ class java/nio/file/NoSuchFileException ]
        frame_type = 0 /* same */
      LineNumberTable:
        line 238: 0
        line 239: 12
        line 242: 16
        line 240: 19
        line 243: 20
    Exceptions:
      throws java.io.IOException

  public void waitAppTerminate();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=4, locals=2, args_size=1
         0: aload_0
Error: Not a FieldRefEntry at index: 61
         1: getfield      ???
         4: ldc2_w        #180                // long 100l
         7: invokestatic  #182                // Method jdk/test/lib/Utils.adjustTimeout:(J)J
Error: Not a FieldRefEntry at index: 97
        10: getstatic     ???
        13: invokevirtual #194                // Method java/lang/Process.waitFor:(JLjava/util/concurrent/TimeUnit;)Z
        16: ifne          34
        19: aload_0
Error: Not a FieldRefEntry at index: 61
        20: getfield      ???
        23: invokevirtual #198                // Method java/lang/Process.destroy:()V
        26: aload_0
Error: Not a FieldRefEntry at index: 61
        27: getfield      ???
        30: invokevirtual #201                // Method java/lang/Process.waitFor:()I
        33: pop
        34: aload_0
Error: Not a FieldRefEntry at index: 87
        35: getfield      ???
        38: invokevirtual #203                // Method java/lang/Thread.join:()V
        41: aload_0
Error: Not a FieldRefEntry at index: 90
        42: getfield      ???
        45: invokevirtual #203                // Method java/lang/Thread.join:()V
        48: goto          58
        51: astore_1
        52: invokestatic  #208                // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
        55: invokevirtual #212                // Method java/lang/Thread.interrupt:()V
        58: return
      Exception table:
         from    to  target type
             0    48    51   Class java/lang/InterruptedException
      StackMapTable: number_of_entries = 3
        frame_type = 34 /* same */
        frame_type = 80 /* same_locals_1_stack_item */
          stack = [ class java/lang/InterruptedException ]
        frame_type = 6 /* same */
      LineNumberTable:
        line 249: 0
        line 250: 19
        line 251: 26
        line 253: 34
        line 254: 41
        line 258: 48
        line 255: 51
        line 256: 52
        line 259: 58

  public void createLock() throws java.io.IOException;
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=1
         0: aload_0
Error: Not a FieldRefEntry at index: 48
         1: getfield      ???
         4: iconst_0
         5: anewarray     #125                // class java/lang/String
         8: invokestatic  #127                // Method java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;
        11: astore_1
        12: aload_1
        13: iconst_0
        14: anewarray     #160                // class java/nio/file/attribute/FileAttribute
        17: invokestatic  #162                // Method java/nio/file/Files.createFile:(Ljava/nio/file/Path;[Ljava/nio/file/attribute/FileAttribute;)Ljava/nio/file/Path;
        20: pop
        21: aload_0
        22: aload_0
Error: Not a FieldRefEntry at index: 48
        23: getfield      ???
        26: invokestatic  #166                // Method lastModified:(Ljava/lang/String;)J
Error: Not a FieldRefEntry at index: 94
        29: putfield      ???
        32: return
      LineNumberTable:
        line 225: 0
        line 227: 12
        line 228: 21
        line 229: 32
    Exceptions:
      throws java.io.IOException

  public void runAppExactJvmOpts(java.lang.String[]) throws java.io.IOException;
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=4, args_size=2
         0: aload_0
         1: aload_1
         2: invokevirtual #326                // Method runAppPrepare:([Ljava/lang/String;)Ljava/util/List;
         5: astore_2
         6: aload_0
         7: aload_2
         8: invokevirtual #330                // Method runAddAppName:(Ljava/util/List;)V
        11: aload_2
        12: aload_0
Error: Not a FieldRefEntry at index: 48
        13: getfield      ???
        16: invokeinterface #248,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        21: pop
        22: aload_0
Error: Not a FieldRefEntry at index: 29
        23: getfield      ???
        26: ifeq          39
        29: aload_2
        30: ldc_w         #334                // String forceCrash
        33: invokeinterface #248,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        38: pop
        39: aload_0
        40: aload_2
        41: invokevirtual #335                // Method printCommandLine:(Ljava/util/List;)V
        44: new           #338                // class java/lang/ProcessBuilder
        47: dup
        48: aload_2
        49: invokespecial #340                // Method java/lang/ProcessBuilder."<init>":(Ljava/util/List;)V
        52: astore_3
        53: aload_0
Error: Not a FieldRefEntry at index: 29
        54: getfield      ???
        57: ifeq          65
        60: aload_3
        61: invokestatic  #342                // Method jdk/test/lib/util/CoreUtils.addCoreUlimitCommand:(Ljava/lang/ProcessBuilder;)Ljava/lang/ProcessBuilder;
        64: astore_3
        65: aload_0
        66: aload_3
        67: invokevirtual #348                // Method java/lang/ProcessBuilder.start:()Ljava/lang/Process;
Error: Not a FieldRefEntry at index: 61
        70: putfield      ???
        73: aload_0
        74: invokevirtual #351                // Method startOutputPumpers:()V
        77: return
      StackMapTable: number_of_entries = 2
        frame_type = 252 /* append */
          offset_delta = 39
          locals = [ class java/util/List ]
        frame_type = 252 /* append */
          offset_delta = 25
          locals = [ class java/lang/ProcessBuilder ]
      LineNumberTable:
        line 361: 0
        line 363: 6
        line 364: 11
        line 365: 22
        line 366: 29
        line 369: 39
        line 371: 44
        line 372: 53
        line 374: 60
        line 377: 65
        line 379: 73
        line 380: 77
    Exceptions:
      throws java.io.IOException

  public static void checkForDumps();
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=6, locals=8, args_size=0
Error: Not a FieldRefEntry at index: 102
         0: getstatic     ???
         3: ldc_w         #439                // String Check for hs_err_pid/core/mdmp files:
         6: invokevirtual #321                // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         9: iconst_0
        10: istore_0
        11: invokedynamic #441,  0            // InvokeDynamic #11:accept:()Ljava/io/FilenameFilter;
        16: astore_1
        17: new           #445                // class java/io/File
        20: dup
        21: ldc_w         #276                // String .
        24: invokespecial #447                // Method java/io/File."<init>":(Ljava/lang/String;)V
        27: aload_1
        28: invokevirtual #448                // Method java/io/File.listFiles:(Ljava/io/FilenameFilter;)[Ljava/io/File;
        31: astore_2
        32: aload_2
        33: arraylength
        34: istore_3
        35: iconst_0
        36: istore        4
        38: iload         4
        40: iload_3
        41: if_icmpge     94
        44: aload_2
        45: iload         4
        47: aaload
        48: astore        5
        50: aload         5
        52: invokevirtual #452                // Method java/io/File.length:()J
        55: lstore        6
Error: Not a FieldRefEntry at index: 102
        57: getstatic     ???
        60: aload         5
        62: invokestatic  #429                // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        65: lload         6
        67: ldc2_w        #454                // long 1024l
        70: ldiv
        71: ldc2_w        #454                // long 1024l
        74: ldiv
        75: lload         6
        77: invokedynamic #456,  0            // InvokeDynamic #12:makeConcatWithConstants:(Ljava/lang/String;JJ)Ljava/lang/String;
        82: invokevirtual #321                // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        85: iinc          0, 1
        88: iinc          4, 1
        91: goto          38
        94: iload_0
        95: ifne          107
Error: Not a FieldRefEntry at index: 102
        98: getstatic     ???
       101: ldc_w         #459                // String None.
       104: invokevirtual #321                // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       107: return


Comments
Changeset: 7bb1999c Author: Ashutosh Mehra <asmehra@openjdk.org> Date: 2023-11-14 14:48:47 +0000 URL: https://git.openjdk.org/jdk/commit/7bb1999c51cdfeb020047e1094229fda1ec5a99d
14-11-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/15973 Date: 2023-09-28 21:23:25 +0000
28-09-2023

I believe this is caused by https://bugs.openjdk.org/browse/JDK-8301996. The change missed out updating the ByteCodeRewriter.java. I agree a test would have caught this issue. I am hoping to have https://bugs.openjdk.org/browse/JDK-8311101 in some time soon. I think I still need one more change before the test can be run successfully.
28-09-2023

After JDK-8294969 integration is serviceability/sa/ClhsdbDumpclass.java test on a problem list with reference to this bug.
18-09-2023

This is likely related to JDK-8305490 and was also caused by JDK-8292818.
15-09-2023

Looking at the first error: public void printCommandLine(java.util.List<java.lang.String>); descriptor: (Ljava/util/List;)V flags: (0x0001) ACC_PUBLIC Code: stack=5, locals=2, args_size=2 Error: Not a FieldRefEntry at index: 102 0: getstatic ??? 3: aload_1 Currently (without JDK-8294969 changes), the test output is: public void printCommandLine(java.util.List<java.lang.String>); descriptor: (Ljava/util/List;)V flags: (0x0001) ACC_PUBLIC Code: stack=5, locals=2, args_size=2 0: getstatic #102 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V 3: aload_1 #102 = Methodref #100.#103 // java/lang/Thread."<init>":(Ljava/lang/Runnable;)V So there is actually a MethodRef at that location, not a FieldRef. Using javap on the javac generated class file, I get: public void printCommandLine(java.util.List<java.lang.String>); descriptor: (Ljava/util/List;)V flags: (0x0001) ACC_PUBLIC Code: stack=5, locals=2, args_size=2 0: getstatic #287 // Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_1 #287 = Fieldref #265.#288 // java/lang/System.out:Ljava/io/PrintStream; Note that test output also has cp #287 correct, so it looks like the issue is simply that the wrong cp entry is being used with the getstatic. It should be #287, not #102. It looks like every field access bytecode is getting the cp index wrong. This would have been detected sooner if we had a test that actually ran the dumped class file. Currently we don't.
15-09-2023

I have to add serviceability/sa/ClhsdbDumpclass.java test on problem list at https://github.com/openjdk/jdk/pull/11411
15-09-2023