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

javac accepts illegal modifier on local class in violation of JLS §14.3

XMLWordPrintable

    • b26
    • 16
    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      macOS version:

      ```
      Software:

          System Software Overview:

            System Version: macOS 13.2 (22D49)
            Kernel Version: Darwin 22.3.0
            Boot Volume: Macintosh HD
            Boot Mode: Normal
            Computer Name: MacBook Pro
            User Name: MacBook
            Secure Virtual Memory: Enabled
            System Integrity Protection: Enabled
            Time since boot: 1 day, 2 hours, 19 minutes

      Hardware:

          Hardware Overview:

            Model Name: MacBook Pro
            Model Identifier: MacBookPro18,1
            Model Number: MK193CH/A
            Chip: Apple M1 Pro
            Total Number of Cores: 10 (8 performance and 2 efficiency)
            Memory: 16 GB
            System Firmware Version: 8419.80.7
            OS Loader Version: 8419.80.7
            Activation Lock Status: Disabled
      ```

      OpenJDK version:

      ```
      openjdk version "11.0.27" 2025-04-15
      OpenJDK Runtime Environment Temurin-11.0.27+6 (build 11.0.27+6)
      OpenJDK 64-Bit Server VM Temurin-11.0.27+6 (build 11.0.27+6, mixed mode)

      openjdk version "17.0.15" 2025-04-15
      OpenJDK Runtime Environment Temurin-17.0.15+6 (build 17.0.15+6)
      OpenJDK 64-Bit Server VM Temurin-17.0.15+6 (build 17.0.15+6, mixed mode, sharing)

      openjdk version "21.0.7" 2025-04-15 LTS
      OpenJDK Runtime Environment Temurin-21.0.7+6 (build 21.0.7+6-LTS)
      OpenJDK 64-Bit Server VM Temurin-21.0.7+6 (build 21.0.7+6-LTS, mixed mode, sharing)
      ```

      A DESCRIPTION OF THE PROBLEM :
      The following test program declares a local class within a code block. When compiled with `javac` of JDK 17 or JDK 21, it compiles without any error. However, compiling the same code using `javac` of JDK 11 or the Eclipse Compiler for Java (ECJ) results in a compilation error.

      ```
      public class Test {
          public static void main(String[] args) {
              var outer = new java.lang.Object() {
                  private class Inner {
                      public void method() {
                          System.out.println("Inner local class method");
                      }
                  }
              };
          }
      }
      ```

      ### Observed Behavior:

      Using `javac` of JDK17 or JDK21, the program compiles successfully without any error.

      ```
      >>> pathToJDK17/javac Test.java
      >>> pathToJDK21/javac Test.java
      ```

      However, using `javac` of JDK 11:

      ```
      >>> pathToJDK11/javac Test.java
      Test.java:4: error: modifier private not allowed here
                  private class Inner {
                          ^
      1 error
      ```

      and, compiling the same code with **ECJ** produces the following error:

      ```java
      >>> java -cp . -jar ecj-4.36.jar --release 21 -d . Test.java
      ----------
      1. ERROR in /Test.java (at line 4)
              private class Inner {
                            ^^^^^
      Illegal modifier for the local class Inner; only abstract or final is permitted
      ----------
      1 problem (1 error)
      ```

      According to the [Java Language Specification, §14.3](https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.3):

      > “It is a compile-time error if a local class or interface declaration has any of the access modifiers public, protected, or private (§6.6).”
      >

      This means local classes must not use access modifiers like `private`.

      ECJ and JDK 11 correctly reject the code, adhering to the specification.

      However, JDK 17 and JDK 21’s `javac` compilers silently accept it, which contradicts the language specification and may indicate a potential bug.

      REGRESSION : Last worked in version 11.0.27

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Compile `Test.java` using `javac` from JDK 17 or JDK 21 — observe that it compiles successfully.
      2. Compile `Test.java` using `javac` from JDK 11 — observe the compilation error.
      3. Compile `Test.java` using ECJ (e.g., version 4.36) — observe the error.
      4. Compare the outputs for consistency with the Java Language Specification.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The program should report a compile-time error.
      ACTUAL -
      The program compiles successfully without any error.

      ---------- BEGIN SOURCE ----------
      public class Test {
          public static void main(String[] args) {
              var outer = new java.lang.Object() {
                  private class Inner {
                      public void method() {
                          System.out.println("Inner local class method");
                      }
                  }
              };
          }
      }
      ---------- END SOURCE ----------

            vromero Vicente Arturo Romero Zaldivar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: