Why is the generated name for a lambda class not the same for identical programs

Viewed 633

source code(of course the project have many other classes)

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        Map<Integer, Integer> src = new HashMap<>();
        Map<Integer, List<Integer>> dst = new HashMap<>();
        Optional<Object> f = dst.values().stream().flatMap((Function<List<Integer>, Stream<?>>) integers -> integers.stream()).filter(b -> !src.containsKey(b)).findFirst();
        f.ifPresent(b -> {
            throw new IllegalStateException("exception [" + b + "]");
        });
    }
}

1.copy project to different path

d:\Users\shell\Documents\workplace\bak\1

d:\Users\shell\Documents\workplace\bak\2

2.execute mvn package in both path

3.check the class file

execute command javap -p in d:\Users\shell\Documents\workplace\bak\1\data\target\classes

public class Test {
    public Test();
    public static void main(java.lang.String[]);
    private static void lambda$main$84(java.lang.Object);
    private static boolean lambda$main$83(java.util.Map, java.lang.Object);
    private static java.util.stream.Stream lambda$main$82(java.util.List);
}

execute command javap -p in d:\Users\shell\Documents\workplace\bak\2\data\target\classes

public class Test {
    public Test();
    public static void main(java.lang.String[]);
    private static void lambda$main$75(java.lang.Object);
    private static boolean lambda$main$74(java.util.Map, java.lang.Object);
    private static java.util.stream.Stream lambda$main$73(java.util.List);
}

why the number of lambda function is different?

is there any way i can make them same?

2 Answers

FWIW, this used to be caused by a bug in OpenJDK. It was fixed in December 2016: https://bugs.openjdk.java.net/browse/JDK-8067422

Currently, when lambda names (for non-serializable lambdas) are generated, the exact name depends on the number of (non-serializable) lamdbas generated so far by the current javac instance. The reason is that the counter for lambda names is not per-file, but per-javac instance. For example, consider:

public class L1 {
   private Runnable r = () -> { };
}

public class L2 {
    private Runnable r = () -> { };
}

doing: javac L1.java L2.java will make L1's lambda use lambda$new$0 and L2's lambda$new$1, while: javac L2.java L1.java will lead to the opposite name assignment.

The problem seems to be simple: LambdaToMethod.LambdaAnalyzerPreprocessor.lambdaCount is not reset before starting with a new top-level.

Related