Skip to content

[core] nested class emitted without 'static' when the InnerClass STATIC flag is stripped #2903

Description

@obus-globus

Issue details

jadx takes a nested class's static modifier straight from the InnerClass attribute and never re-infers it.
R8 can strip the STATIC flag from a class that is in fact static (its constructor takes no synthetic outer-this argument).
The class is then emitted non-static, so a new Outer.Inner() from a static context does not compile.

The information to recover it is already in the bytecode: a non-static inner class's constructor has a synthetic first argument of the outer type (this is exactly the check in MethodNode.java#L535-L540).
A member class whose constructors have no such argument is static.
The subtlety is that this must apply only to member classes: local and anonymous classes also lack the outer-this arg but cannot be static.
A naive add-only inference over any inner class with no outer-this ctor wrongly marks a non-inlined $1-style or local class static (it regresses TestIncorrectAnonymousClass), and there is no enclosing-method info to separate member classes from those, so this needs a signal beyond the class name.

Sample

Outer.smali (member class a with a static factory):

.class public La;
.super Ljava/lang/Object;

.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        La$b;
    }
.end annotation

.method public static make()La$b;
    .registers 1
    new-instance v0, La$b;
    invoke-direct {v0}, La$b;-><init>()V
    return-object v0
.end method

Inner.smali (static in fact -- no outer-this ctor arg -- but the InnerClass STATIC flag is absent):

.class public La$b;
.super Ljava/lang/Object;

.annotation system Ldalvik/annotation/EnclosingClass;
    value = La;
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x1
    name = "b"
.end annotation

.method public constructor <init>()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method

Output on master (8c28a85), does not compile (new a.b() in a static method needs an enclosing a instance):

public class a {
    public class b {
    }

    public static a.b make() {
        return new a.b();
    }
}

Jadx version

master 8c28a85 (current HEAD)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions