Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full support for "desugared" lambdas #523

Open
3 of 5 tasks
skylot opened this issue Mar 27, 2019 · 1 comment
Open
3 of 5 tasks

Full support for "desugared" lambdas #523

skylot opened this issue Mar 27, 2019 · 1 comment
Labels
Core Issues in jadx-core module new feature
Milestone

Comments

@skylot
Copy link
Owner

skylot commented Mar 27, 2019

New d8 android compiler allows to use Java 8 lambdas, but to make it work on old Android versions d8 convert (desugar) lambdas to synthetic classes and methods.
This issue continues work on lambda inlining started in #467.
Known issues:

  • Lambda classes inlined
  • Some lambda classes used by INSTANCE static field
  • Not all arguments inlined and synthetic fields in inlined classes not removed
  • lambda$* methods must be inlined
  • lambdas initialized at fields declaration (with anonymous class as a field type)

Note: Inlining Kotlin lambdas change code semantic by removing extend of kotlin.jvm.internal.Lambda. To disable such inlines use flag --no-inline-kotlin-lambda in jadx-cli and option Allow to inline Kotlin Lambdas in jadx-gui.

@pubiqq
Copy link
Contributor

pubiqq commented Aug 8, 2024

Small sample:

Original class

package com.example;

import java.util.function.Function;

class TestJavaClass {

    private final Function<String, String> f = x -> x;

    String test() {
        return f.apply("2");
    }
}

Smali

###### Class com.example.TestJavaClass (com.example.TestJavaClass)
.class Lcom/example/TestJavaClass;
.super Ljava/lang/Object;
.source "TestJavaClass.java"


# instance fields
.field private final f:Ljava/util/function/Function;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "Ljava/util/function/Function<",
            "Ljava/lang/String;",
            "Ljava/lang/String;",
            ">;"
        }
    .end annotation
.end field


# direct methods
.method constructor <init>()V
    .registers 2

    .line 5
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    .line 7
    new-instance v0, Lcom/example/TestJavaClass$$ExternalSyntheticLambda0;

    invoke-direct {v0}, Lcom/example/TestJavaClass$$ExternalSyntheticLambda0;-><init>()V

    iput-object v0, p0, Lcom/example/TestJavaClass;->f:Ljava/util/function/Function;

    return-void
.end method

.method static synthetic lambda$new$0(Ljava/lang/String;)Ljava/lang/String;
    .registers 1
    .param p0, "x"    # Ljava/lang/String;

    .line 7
    return-object p0
.end method


# virtual methods
.method test()Ljava/lang/String;
    .registers 3

    .line 10
    iget-object v0, p0, Lcom/example/TestJavaClass;->f:Ljava/util/function/Function;

    const-string v1, "2"

    invoke-interface {v0, v1}, Ljava/util/function/Function;->apply(Ljava/lang/Object;)Ljava/lang/Object;

    move-result-object v0

    check-cast v0, Ljava/lang/String;

    return-object v0
.end method

###### Class com.example.TestJavaClass$$ExternalSyntheticLambda0 (com.example.TestJavaClass$$ExternalSyntheticLambda0)
.class public final synthetic Lcom/example/TestJavaClass$$ExternalSyntheticLambda0;
.super Ljava/lang/Object;
.source "D8$$SyntheticClass"

# interfaces
.implements Ljava/util/function/Function;


# direct methods
.method public synthetic constructor <init>()V
    .registers 1

    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
.method public final apply(Ljava/lang/Object;)Ljava/lang/Object;
    .registers 2

    check-cast p1, Ljava/lang/String;

    invoke-static {p1}, Lcom/example/TestJavaClass;->lambda$new$0(Ljava/lang/String;)Ljava/lang/String;

    move-result-object p1

    return-object p1
.end method

Decompiled class (jadx-1.5.0)

package com.example;

import java.util.function.Function;

/* loaded from: classes8.dex */
package com.example;

import java.util.function.Function;

/* loaded from: classes8.dex */
class TestJavaClass {
    private final Function<String, String> f = new Function() { // from class: com.example.TestJavaClass$$ExternalSyntheticLambda0
        @Override // java.util.function.Function
        public final Object apply(Object obj) {
            return TestJavaClass.lambda$new$0((String) obj);
        }
    };

    TestJavaClass() {
    }

    /* JADX INFO: Access modifiers changed from: package-private */
    public static /* synthetic */ String lambda$new$0(String x) {
        return x;
    }

    String test() {
        return this.f.apply("2");
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core Issues in jadx-core module new feature
Projects
None yet
Development

No branches or pull requests

2 participants