eclipse-windowbuilder / windowbuilder

Eclipse Windowbuilder
https://projects.eclipse.org/projects/tools.windowbuilder
Eclipse Public License 1.0
80 stars 30 forks source link

[1.8] Improve support for outdated JDK versions #930

Closed ptziegler closed 3 weeks ago

ptziegler commented 3 weeks ago

The JDT compiler is unable to calculate the argument names of a method binding when a JDK 8 is used and simply returns an empty array. This then leads to an out-of-bounds exception, as the number of parameter types no longer matches the number of parameter names.

Note that this issue only happens with a proper JDK 8, but not an e.g. JDK 17 with compiler compliance set to Java 8.

The parameter names themselves only seem to be relevant for cosmetic reason, so they are now simply ignored (together with a warning), rather than causing the editor to crash.

From a technical perspective, the problem can be isolated to one of the internal classes of the JDT compiler:

org.eclipse.jdt.internal.compiler.classfmt.MethodInfo -> getArgumentNames() -> readCodeAttribute() -> decodeCodeAttribute()

The offset that is supposed to point to the "LocalVariableTable" is instead pointing to the "LineNumberTable" and as a result, the compiler is unable to extract the attribute names.

ptziegler commented 3 weeks ago

The problem is in this method here, if anyone is curious:

private void decodeCodeAttribute(int offset) {
    int readOffset = offset + 10;
    int codeLength = u4At(readOffset);
    readOffset += (4 + codeLength);
    int exceptionTableLength = u2At(readOffset);
    readOffset += 2;
    if (exceptionTableLength != 0) {
        for (int i = 0; i < exceptionTableLength; i++) {
            readOffset += 8;
        }
    }
    int attributesCount = u2At(readOffset);
    readOffset += 2;
    for (int i = 0; i < attributesCount; i++) {
        int utf8Offset = this.constantPoolOffsets[u2At(readOffset)] - this.structOffset;
        char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
        if (CharOperation.equals(attributeName, AttributeNamesConstants.LocalVariableTableName)) {
            decodeLocalVariableAttribute(readOffset, codeLength);
        }
        readOffset += (6 + u4At(readOffset + 2));
    }
}

I though about raising an issue over at the JDT project. But I dismissed the idea, because it only happens with a JDK 8, but not a JDK 17 or 21. In the end, I think the response would be similar to what I believe, which is that people should stop using a JDK that's well past its expiration date...

ptziegler commented 3 weeks ago

This also relates to numerous issues, not only but also including:

https://github.com/eclipse-windowbuilder/windowbuilder/issues/916 https://github.com/eclipse-windowbuilder/windowbuilder/issues/827 https://github.com/eclipse-windowbuilder/windowbuilder/issues/758 https://github.com/eclipse-windowbuilder/windowbuilder/issues/634 https://github.com/eclipse-windowbuilder/windowbuilder/issues/533