Skip to content

Fix field initialization and refactor DecompileClass - #10

Merged
leslieyip02 merged 5 commits into
masterfrom
fix/field-default-value
Sep 10, 2026
Merged

Fix field initialization and refactor DecompileClass#10
leslieyip02 merged 5 commits into
masterfrom
fix/field-default-value

Conversation

@leslieyip02

@leslieyip02 leslieyip02 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Fix field initialization

The DecompileClass.decompileField always assigns an initializer:

private fun decompileField(node: FieldNode): FieldDeclaration {
// attrs (ignore?)
val modifiers = Flag.toModifiers(Flag.fieldFlags(node.access))
val annotations: NodeList<AnnotationExpr> = decompileAnnotations(
node.visibleAnnotations,
node.invisibleAnnotations,
node.visibleTypeAnnotations,
node.invisibleTypeAnnotations,
)
val type =
if (node.signature != null) Signature.typeSignature(node.signature) else Descriptor.fieldDescriptor(node.desc)
val name = SimpleName(node.name)
val initializer = decompileLiteral(node.value)
val variables = NodeList<VariableDeclarator>(VariableDeclarator(type, name, initializer))
return FieldDeclaration(modifiers, annotations, variables)
}

It does so by decompiling the node's value as a literal and using that literal as the field's initializer. However, consider the following:

// Foo.java
class Foo {
  public int value;
}

Under the current logic, node.value is null, so decompileLiteral(node.value) is also null. When running jade decompile Foo.class ., the result is

/** Source File: Foo.java
* Class-file Format Version: 63
* Source Debug Extension: null // See JSR-45 https://www.jcp.org/en/jsr/detail?id=045
*/
class Foo extends java.lang.Object {

    public int value = null;

    Foo() {
        super();
        return;
    }
}

This is wrong since null cannot be assigned to primitives. This can be fixed by omitting the initializer argument if node.value is null. Applying the fix, the decompiled result can then be recompiled:

/**
 * Source File: Foo.java
 * Class-file Format Version: 63
 * Source Debug Extension: null // See JSR-45 https://www.jcp.org/en/jsr/detail?id=045
 */
class Foo extends java.lang.Object {

    public int value;

    Foo() {
        super();
        return;
    }
}

If we do set an initial value, the value is set in the constructor (this seems correct?):

Before After
class Foo {
  public int value = 42;
}
class Foo extends java.lang.Object {

    public int value;

    Foo() {
        super();
        this.value = 42;
        return;
    }
}

Refactor

Additionally, DecompileClass was also refactored and improved:

  1. Add KDoc for DecompileClass
  2. Refactor DecompileClass
    a. De-bloat large methods (i.e. decompileMethod and decompileClass) with helper functions
    b. Readability improvements (i.e. renamed some variables for better clarity, reorganized certain sections of code)
    c. Adding file-level comment using JavadocComment instead of BlockComment (the previous approach had alignment issues)

@leslieyip02
leslieyip02 force-pushed the fix/field-default-value branch from ff69314 to 28578ed Compare September 7, 2026 06:01
@leslieyip02 leslieyip02 changed the title Fix field initialization and refactor DecompileClass Fix field initialization and refactor DecompileClass Sep 7, 2026
@leslieyip02
leslieyip02 force-pushed the fix/field-default-value branch 2 times, most recently from ee1ee59 to 53f2224 Compare September 8, 2026 03:23
- Break up big methods (i.e. decompileMethod and decompileClass) into
  helpers for better readability
- Renamed some variables for readability
- Update access modifiers
- Use JavadocComment instead of BlockComment for file-level comment
@leslieyip02
leslieyip02 force-pushed the fix/field-default-value branch from 53f2224 to 8f1a661 Compare September 10, 2026 08:21
@leslieyip02
leslieyip02 merged commit 844706a into master Sep 10, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant