Janino

Explicit constructor invocation in inner classes leads to compilation error

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Environment:
    java 6.0rc, win2k, janino 2.5.1 (same with 2.3.18)
  • Number of attachments :
    1

Description

The same for usual classes works fine. And inner classes with only one c'tor also work fine.

I get the following exception via source class loader (javac doesn't complain):

Caused by: java.lang.RuntimeException: JaninoBug$Sub.JaninoBug$Sub(int[] a): Operand stack underrun at offset 7
at org.codehaus.janino.CodeContext.flowAnalysis(CodeContext.java)
at org.codehaus.janino.CodeContext.flowAnalysis(CodeContext.java)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler$1.visitMemberClassDeclaration(UnitCompiler.java)
at org.codehaus.janino.Java$MemberClassDeclaration.accept(Java.java)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler$1.visitPackageMemberClassDeclaration(UnitCompiler.java)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java)
at org.codehaus.janino.JavaSourceClassLoader.generateBytecodes(JavaSourceClassLoader.java)
at org.codehaus.janino.JavaSourceClassLoader.findClass(JavaSourceClassLoader.java)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
[...]

I'm not really sure if I'm spot on with the summary. Well, I attached some minimalistic example, which should outline the problem.

Activity

Hide
Arno Unkrig added a comment -

You were close. The reason being is not the two constructors, but the expicit constructor invocation.

Changed the summary line accordingly.

Added a JUNIT test to ReportedBugs.java that reproduces the problem.

Show
Arno Unkrig added a comment - You were close. The reason being is not the two constructors, but the expicit constructor invocation. Changed the summary line accordingly. Added a JUNIT test to ReportedBugs.java that reproduces the problem.
Hide
Arno Unkrig added a comment -

Got it!

Will be fixed in version 2.5.2 (not scheduled yet).

The quick fix for the time being is to change this method of "UnitCompiler" as follows:

private boolean compile2(Java.AlternateConstructorInvocation aci) throws CompileException {
        Java.ConstructorDeclarator declaringConstructor = (Java.ConstructorDeclarator) aci.getEnclosingScope();
        IClass                     declaringIClass = this.resolve(declaringConstructor.getDeclaringClass());

        this.writeOpcode(aci, Opcode.ALOAD_0);
        if (declaringIClass.getOuterIClass() != null) this.writeOpcode(aci, Opcode.ALOAD_1);
        this.invokeConstructor(
            (Java.Located) aci,                // located
            (Java.Scope) declaringConstructor, // scope
            (Java.Rvalue) null,                // optionalEnclosingInstance
            declaringIClass,                   // targetClass
            aci.arguments                      // arguments
        );
        return true;
    }
Show
Arno Unkrig added a comment - Got it! Will be fixed in version 2.5.2 (not scheduled yet). The quick fix for the time being is to change this method of "UnitCompiler" as follows:
private boolean compile2(Java.AlternateConstructorInvocation aci) throws CompileException {
        Java.ConstructorDeclarator declaringConstructor = (Java.ConstructorDeclarator) aci.getEnclosingScope();
        IClass                     declaringIClass = this.resolve(declaringConstructor.getDeclaringClass());

        this.writeOpcode(aci, Opcode.ALOAD_0);
        if (declaringIClass.getOuterIClass() != null) this.writeOpcode(aci, Opcode.ALOAD_1);
        this.invokeConstructor(
            (Java.Located) aci,                // located
            (Java.Scope) declaringConstructor, // scope
            (Java.Rvalue) null,                // optionalEnclosingInstance
            declaringIClass,                   // targetClass
            aci.arguments                      // arguments
        );
        return true;
    }
Hide
jos hirth added a comment -

Awesome!

Show
jos hirth added a comment - Awesome!

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: