Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 548
shell Avatar asked Mar 10 '16 07:03

shell


1 Answers

Looking into javac source you may notice that the corresponding counter (which is appended to the lambda method name) is defined as an instance field in the LambdaAnalyzerPreprocessor which is reused for the whole compilation process. It's incremented on every lambda occurrence. So if I compile your class only, I will have numbers started from 0:

> javac Test.java
> javap -p Test
Compiled from "Test.java"
public class Test {
  public Test();
  public static void main(java.lang.String[]);
  private static void lambda$main$2(java.lang.Object);
  private static boolean lambda$main$1(java.util.Map, java.lang.Object);
  private static java.util.stream.Stream lambda$main$0(java.util.List);
}

But if I create one more class

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

And compile them together I will see the counter incremented:

> javac Test2.java Test.java 
> javap -p Test
Compiled from "Test.java"
public class Test {
  public Test();
  public static void main(java.lang.String[]);
  private static void lambda$main$3(java.lang.Object);
  private static boolean lambda$main$2(java.util.Map, java.lang.Object);
  private static java.util.stream.Stream lambda$main$1(java.util.List);
}

So this is not the maven problem, this is how javac compiler works.

If you definitely need stable compilation results I may suggest you to try Eclipse Compiler for Java. Seems that it has no such problem:

>java -jar org.eclipse.jdt.core_3.11.1.v20150902-1521.jar -8 Test2.java Test.java
>javap -p Test
Compiled from "Test.java"
public class Test {
  public Test();
  public static void main(java.lang.String[]);
  private static java.util.stream.Stream lambda$0(java.util.List);
  private static boolean lambda$1(java.util.Map, java.lang.Object);
  private static void lambda$2(java.lang.Object);
}

Refer to this question on how to integrate ecj with maven.

like image 132
Tagir Valeev Avatar answered Oct 14 '22 00:10

Tagir Valeev