RFR: 8292755: Non-default method in interface leads to a stack overflow in JShell

Jan Lahoda jlahoda at openjdk.org
Thu Sep 8 16:54:16 UTC 2022


Consider this snippet sent to JShell:

interface I {
    void test() {
        try {
        } catch (IllegalStateException ex) {
            throw new RuntimeException(ex);
        }
    }
}


This leads to a crash:

Exception in thread "main" java.lang.InternalError: Exception during analyze - java.lang.StackOverflowError
        at jdk.jshell/jdk.jshell.TaskFactory$AnalyzeTask.analyze(TaskFactory.java:415)
        at jdk.jshell/jdk.jshell.TaskFactory$AnalyzeTask.<init>(TaskFactory.java:406)
        at jdk.jshell/jdk.jshell.TaskFactory.lambda$analyze$1(TaskFactory.java:178)
        at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193)
        at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206)
        at jdk.jshell/jdk.jshell.TaskFactory.analyze(TaskFactory.java:175)
        at jdk.jshell/jdk.jshell.TaskFactory.analyze(TaskFactory.java:161)
        at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1060)
        at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:893)
        at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140)
        at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:493)
        at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3622)
        at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1347)
        at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1245)
        at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:1216)
        at jdk.jshell/jdk.internal.jshell.tool.JShellTool.start(JShellTool.java:1000)
        at jdk.jshell/jdk.internal.jshell.tool.JShellToolBuilder.start(JShellToolBuilder.java:261)
        at jdk.jshell/jdk.internal.jshell.tool.JShellToolProvider.main(JShellToolProvider.java:120)
Caused by: java.lang.IllegalStateException: java.lang.StackOverflowError
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:383)
        at jdk.jshell/jdk.jshell.TaskFactory$AnalyzeTask.analyze(TaskFactory.java:412)
        ... 18 more
Caused by: java.lang.StackOverflowError
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1077)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSuperType(Types.java:1304)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1086)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1077)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSuperType(Types.java:1304)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1086)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1077)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSuperType(Types.java:1304)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1086)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1077)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSuperType(Types.java:1304)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1086)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1077)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSuperType(Types.java:1304)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1086)
        at jdk.compiler/com.sun.tools.javac.code.Types.isSubtype(Types.java:1077)
...


The reason is as follows: when javac's `Attr` sees a method, it checks its modifiers, and if there's a e.g. non-default method with a body in an interface, it won't attribute the body. But, JShell asks javac to go to `Flow`, so `Attr.postAttr` will fill some stub data. But the stub data then lead `Flow` to the stack overflow when checking thrown exceptions.

The proposed fix is to attribute method bodies even if the modifiers are wrong. The proper errors are reported as before, of course, but in addition the body is attributed, so that JShell and other clients can work with the body.

-------------

Commit messages:
 - 8292755: Non-default method in interface leads to a stack overflow in JShell

Changes: https://git.openjdk.org/jdk/pull/10221/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=10221&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8292755
  Stats: 194 lines in 3 files changed: 185 ins; 8 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/10221.diff
  Fetch: git fetch https://git.openjdk.org/jdk pull/10221/head:pull/10221

PR: https://git.openjdk.org/jdk/pull/10221


More information about the compiler-dev mailing list