Skip to content

Commit

Permalink
make desugar resilient to unrelated lambdas being dumped while it runs
Browse files Browse the repository at this point in the history
RELNOTES: None.

PiperOrigin-RevId: 178952440
  • Loading branch information
kevin1e100 authored and Copybara-Service committed Dec 13, 2017
1 parent 0cb96d1 commit 817b535
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
18 changes: 18 additions & 0 deletions src/test/java/com/google/devtools/build/android/desugar/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,24 @@ genrule(
],
)

# Regression test for b/70415451
genrule(
name = "desugar_guava_at_head",
srcs = [
"//third_party:guava-jars",
# Depend on Jacoco runtime in case testdata was built with coverage
# instrumentation
"//third_party/java/jacoco:blaze-agent",
"//tools/defaults:android_jar",
],
outs = ["guava_at_head_desugared.jar"],
cmd = "$(location //src/tools/android/java/com/google/devtools/build/android/desugar:Desugar) " +
"-i $(location //third_party:guava-jars) -o $@ " +
"--bootclasspath_entry $(location //tools/defaults:android_jar)",
tags = ["no_windows"],
tools = ["//src/tools/android/java/com/google/devtools/build/android/desugar:Desugar"],
)

java_binary(
name = "generate_lambda_with_constant_arguments",
srcs = ["Bug62060793TestDataGenerator.java"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,27 @@
package com.google.devtools.build.android.desugar;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Iterables.getOnlyElement;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.Set;

class LambdaClassMaker {

static final String LAMBDA_METAFACTORY_DUMPER_PROPERTY = "jdk.internal.lambda.dumpProxyClasses";

private final Path rootDirectory;
private final Map<Path, LambdaInfo> generatedClasses = new LinkedHashMap<>();
private final Set<Path> existingPaths = new HashSet<>();

public LambdaClassMaker(Path rootDirectory) {
checkArgument(
Expand All @@ -42,16 +44,19 @@ public LambdaClassMaker(Path rootDirectory) {

public void generateLambdaClass(String invokerInternalName, LambdaInfo lambdaInfo,
MethodHandle bootstrapMethod, ArrayList<Object> bsmArgs) throws IOException {
// Invoking the bootstrap method will dump the generated class
// Invoking the bootstrap method will dump the generated class. Ignore any pre-existing
// matching files, which can come from desugar's implementation using classes being desugared.
existingPaths.addAll(findUnprocessed(invokerInternalName + "$$Lambda$"));
try {
bootstrapMethod.invokeWithArguments(bsmArgs);
} catch (Throwable e) {
throw new IllegalStateException("Failed to generate lambda class for class "
+ invokerInternalName + " using " + bootstrapMethod + " with arguments " + bsmArgs, e);
}

Path generatedClassFile = findOnlyUnprocessed(invokerInternalName + "$$Lambda$");
Path generatedClassFile = getOnlyElement(findUnprocessed(invokerInternalName + "$$Lambda$"));
generatedClasses.put(generatedClassFile, lambdaInfo);
existingPaths.add(generatedClassFile);
}

/**
Expand All @@ -64,26 +69,22 @@ public ImmutableMap<Path, LambdaInfo> drain() {
return result;
}

private Path findOnlyUnprocessed(String pathPrefix) throws IOException {
private ImmutableList<Path> findUnprocessed(String pathPrefix) throws IOException {
// pathPrefix is an internal class name prefix containing '/', but paths obtained on Windows
// will not contain '/' and searches will fail. So, construct an absolute path from the given
// string and use its string representation to find the file we need regardless of host
// system's file system
Path rootPathPrefix = rootDirectory.resolve(pathPrefix);
final String rootPathPrefixStr = rootPathPrefix.toString();

// TODO(bazel-team): This could be much nicer with lambdas
try (Stream<Path> paths =
Files.list(rootPathPrefix.getParent())
.filter(
new Predicate<Path>() {
@Override
public boolean test(Path path) {
return path.toString().startsWith(rootPathPrefixStr)
&& !generatedClasses.containsKey(path);
}
})) {
return Iterators.getOnlyElement(paths.iterator());
if (!Files.exists(rootPathPrefix.getParent())) {
return ImmutableList.of();
}
return Files.list(rootPathPrefix.getParent())
.filter(
path ->
path.toString().startsWith(rootPathPrefixStr)
&& !existingPaths.contains(path))
.collect(ImmutableList.toImmutableList());
}
}

0 comments on commit 817b535

Please sign in to comment.