RFR: 8340840: jshell ClassFormatError when making inner class static

Maurizio Cimadamore mcimadamore at openjdk.org
Fri Oct 17 16:35:20 UTC 2025


On Tue, 7 Oct 2025 07:15:50 GMT, Jan Lahoda <jlahoda at openjdk.org> wrote:

> Consider a JShell interaction like:
> 
> jshell> class O { class I {} }
> |  created class O
> 
> jshell> var i = new O().new I();
> i ==> O$I at 77caeb3e
> 
> jshell> class O { static class I {} }
> Exception in thread "main" java.lang.ClassFormatError: class not in class file format
>         at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396)
>         at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90)
>         at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312)
>         at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120)
>         at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
>         at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722)
>         at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
>         at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
>         at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
>         at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
>         at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
>         at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
>         at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
>         at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121)
>         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.compile(TaskFactory.java:186)
>         at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100)
>         at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901)
>         at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140)
>         at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513)
>         at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633)
>         at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353)
>         at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251)
>         at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:...

javac changes look good (did not look at the jshell part)

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java line 3155:

> 3153:                     name = names.one;
> 3154:                 ClassSymbol member = enterClass(name, outer);
> 3155:                 if ((member.flags_field & FROM_SOURCE) == 0) {

I agree with the fix -- I guess I'd slightly prefer to see a warning if a mismatch is detected, but I'll leave that to you.

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

Marked as reviewed by mcimadamore (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3351081584
PR Review Comment: https://git.openjdk.org/jdk/pull/27665#discussion_r2440559516


More information about the compiler-dev mailing list