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

Jan Lahoda jlahoda at openjdk.org
Wed Sep 14 08:53:32 UTC 2022


On Thu, 8 Sep 2022 16:46:49 GMT, Jan Lahoda <jlahoda at openjdk.org> wrote:

> 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.

Thanks, Vicente!

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

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


More information about the compiler-dev mailing list