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

Move debug class dump logic from ClassInstrumentor to SandboxClassLoader #6162

Merged
merged 1 commit into from
Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package org.robolectric.internal.bytecode;

import com.google.common.base.Strings;
import java.io.IOException;
import java.lang.invoke.MethodType;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicInteger;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
Expand All @@ -35,17 +29,12 @@

public abstract class ClassInstrumentor {
private static final String ROBO_INIT_METHOD_NAME = "$$robo$init";
// The directory where instrumented class files will be dumped
private static final String DUMP_CLASSES_PROPERTY = "robolectric.dumpClassesDirectory";
private static final AtomicInteger DUMP_CLASSES_COUNTER = new AtomicInteger();
static final Type OBJECT_TYPE = Type.getType(Object.class);
private static final ShadowImpl SHADOW_IMPL = new ShadowImpl();
final Decorator decorator;
final String dumpClassesDirectory;

protected ClassInstrumentor(Decorator decorator) {
this.decorator = decorator;
this.dumpClassesDirectory = System.getProperty(DUMP_CLASSES_PROPERTY, "");
}

private MutableClass analyzeClass(
Expand Down Expand Up @@ -83,18 +72,7 @@ public String map(final String internalName) {
ClassRemapper visitor = new ClassRemapper(writer, remapper);
classNode.accept(visitor);

byte[] classBytes = writer.toByteArray();
if (!Strings.isNullOrEmpty(dumpClassesDirectory)) {
String outputClassName =
mutableClass.getName() + "-robo-instrumented-" + DUMP_CLASSES_COUNTER.getAndIncrement();
Path path = Paths.get(dumpClassesDirectory, outputClassName + ".class");
try {
Files.write(path, classBytes);
} catch (IOException e) {
throw new AssertionError(e);
}
}
return classBytes;
return writer.toByteArray();
}

public byte[] instrument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
import static com.google.common.base.StandardSystemProperty.PATH_SEPARATOR;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import org.robolectric.util.Logger;
import org.robolectric.util.PerfStatsCollector;
Expand All @@ -21,10 +26,15 @@
* shadow classes.
*/
public class SandboxClassLoader extends URLClassLoader {
// The directory where instrumented class files will be dumped
private static final String DUMP_CLASSES_PROPERTY = "robolectric.dumpClassesDirectory";
private static final AtomicInteger DUMP_CLASSES_COUNTER = new AtomicInteger();

private final InstrumentationConfiguration config;
private final ResourceProvider resourceProvider;
private final ClassInstrumentor classInstrumentor;
private final ClassNodeProvider classNodeProvider;
private final String dumpClassesDirectory;

/** Constructor for use by tests. */
SandboxClassLoader(InstrumentationConfiguration config) {
Expand Down Expand Up @@ -55,6 +65,7 @@ protected byte[] getClassBytes(String internalClassName) throws ClassNotFoundExc
return getByteCode(internalClassName);
}
};
this.dumpClassesDirectory = System.getProperty(DUMP_CLASSES_PROPERTY, "");
}

private static URL[] getClassPathUrls(ClassLoader classloader) {
Expand Down Expand Up @@ -133,6 +144,7 @@ protected Class<?> maybeInstrumentClass(String className) throws ClassNotFoundEx
ClassDetails classDetails = new ClassDetails(origClassBytes);
if (config.shouldInstrument(classDetails)) {
bytes = classInstrumentor.instrument(origClassBytes, config, classNodeProvider);
maybeDumpClassBytes(classDetails, bytes);
} else {
bytes = postProcessUninstrumentedClass(classDetails, origClassBytes);
}
Expand All @@ -146,6 +158,19 @@ protected Class<?> maybeInstrumentClass(String className) throws ClassNotFoundEx
}
}

private void maybeDumpClassBytes(ClassDetails classDetails, byte[] classBytes) {
if (!Strings.isNullOrEmpty(dumpClassesDirectory)) {
String outputClassName =
classDetails.getName() + "-robo-instrumented-" + DUMP_CLASSES_COUNTER.getAndIncrement();
Path path = Paths.get(dumpClassesDirectory, outputClassName + ".class");
try {
Files.write(path, classBytes);
} catch (IOException e) {
throw new AssertionError(e);
}
}
}

protected byte[] postProcessUninstrumentedClass(
ClassDetails classDetails, byte[] origClassBytes) {
return origClassBytes;
Expand Down