Add GN build rules to allow java_assertion_enabler to enable Java asserts.
Also modify java_assertion_enabler to resolve cycle dependency issue and empty jar issue. BUG=462676,665157,665478 Review-Url: https://codereview.chromium.org/2497043002 Cr-Original-Commit-Position: refs/heads/master@{#432521} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 5d3328f05a88be232e11d2ce34bffa64ca2362a5
This commit is contained in:
Родитель
0f22313e62
Коммит
9f06956677
|
@ -5,12 +5,11 @@
|
|||
import("//build/config/android/rules.gni")
|
||||
|
||||
java_binary("java_assertion_enabler") {
|
||||
testonly = true
|
||||
java_files =
|
||||
[ "java/org/chromium/javaassertionenabler/AssertionEnabler.java" ]
|
||||
main_class = "org.chromium.javaassertionenabler.AssertionEnabler"
|
||||
deps = [
|
||||
"//third_party/guava:guava_java",
|
||||
"//third_party/ow2_asm:asm_java",
|
||||
]
|
||||
wrapper_script_name = "helper/java_assertion_enabler"
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
package org.chromium.javaassertionenabler;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
|
@ -14,21 +12,30 @@ import org.objectweb.asm.Opcodes;
|
|||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* An application that enables Java ASSERT statements by modifying Java bytecode. It takes in a JAR
|
||||
* file, modifies bytecode of classes that use ASSERT, and outputs the bytecode to a new JAR file.
|
||||
*/
|
||||
class AssertionEnabler {
|
||||
static final String ASSERTION_DISABLED_NAME = "$assertionsDisabled";
|
||||
static final String CLASS_FILE_SUFFIX = ".class";
|
||||
static final String STATIC_INITIALIZER_NAME = "<clinit>";
|
||||
static final String ASSERTION_DISABLED_NAME = "$assertionsDisabled";
|
||||
static final String TEMPORARY_FILE_SUFFIX = ".temp";
|
||||
|
||||
static final int BUFFER_SIZE = 16384;
|
||||
|
||||
static class AssertionEnablerVisitor extends ClassVisitor {
|
||||
AssertionEnablerVisitor(ClassWriter writer) {
|
||||
|
@ -68,33 +75,53 @@ class AssertionEnabler {
|
|||
}
|
||||
}
|
||||
|
||||
static byte[] readAllBytes(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
int numRead = 0;
|
||||
byte[] data = new byte[BUFFER_SIZE];
|
||||
while ((numRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, numRead);
|
||||
}
|
||||
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
static void enableAssertionInJar(String inputJarPath, String outputJarPath) {
|
||||
try (JarOutputStream outputStream = new JarOutputStream(
|
||||
new BufferedOutputStream(new FileOutputStream(outputJarPath)))) {
|
||||
JarFile jarFile = new JarFile(inputJarPath);
|
||||
for (JarEntry entry : Collections.list(jarFile.entries())) {
|
||||
try (BufferedInputStream inputStream = new BufferedInputStream(
|
||||
jarFile.getInputStream(entry))) {
|
||||
byte[] byteCode = ByteStreams.toByteArray(inputStream);
|
||||
String tempJarPath = outputJarPath + TEMPORARY_FILE_SUFFIX;
|
||||
try (ZipInputStream inputStream = new ZipInputStream(
|
||||
new BufferedInputStream(new FileInputStream(inputJarPath)));
|
||||
ZipOutputStream tempStream = new ZipOutputStream(
|
||||
new BufferedOutputStream(new FileOutputStream(tempJarPath)))) {
|
||||
ZipEntry entry = null;
|
||||
|
||||
while ((entry = inputStream.getNextEntry()) != null) {
|
||||
byte[] byteCode = readAllBytes(inputStream);
|
||||
|
||||
if (entry.isDirectory() || !entry.getName().endsWith(CLASS_FILE_SUFFIX)) {
|
||||
outputStream.putNextEntry(entry);
|
||||
outputStream.write(byteCode);
|
||||
outputStream.closeEntry();
|
||||
tempStream.putNextEntry(entry);
|
||||
tempStream.write(byteCode);
|
||||
tempStream.closeEntry();
|
||||
continue;
|
||||
}
|
||||
ClassReader reader = new ClassReader(byteCode);
|
||||
ClassWriter writer = new ClassWriter(reader, 0);
|
||||
reader.accept(new AssertionEnablerVisitor(writer), 0);
|
||||
byte[] patchedByteCode = writer.toByteArray();
|
||||
outputStream.putNextEntry(new JarEntry(entry.getName()));
|
||||
outputStream.write(patchedByteCode);
|
||||
outputStream.closeEntry();
|
||||
}
|
||||
tempStream.putNextEntry(new ZipEntry(entry.getName()));
|
||||
tempStream.write(patchedByteCode);
|
||||
tempStream.closeEntry();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
Path src = Paths.get(tempJarPath);
|
||||
Path dest = Paths.get(outputJarPath);
|
||||
Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException ioException) {
|
||||
throw new RuntimeException(ioException);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# Some projects (e.g. V8) do not have non-build directories DEPS'ed in.
|
||||
import("//build_overrides/build.gni")
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/dcheck_always_on.gni")
|
||||
import("//build/config/sanitizers/sanitizers.gni")
|
||||
|
||||
assert(is_android)
|
||||
|
@ -1006,11 +1007,12 @@ if (enable_java_templates) {
|
|||
_rebased_build_config = rebase_path(_build_config, root_build_dir)
|
||||
assert(_rebased_build_config != "" || true) # Mark used.
|
||||
|
||||
_proguard_preprocess =
|
||||
defined(invoker.proguard_preprocess) && invoker.proguard_preprocess
|
||||
_input_jar_path = invoker.input_jar_path
|
||||
_output_jar_path = invoker.output_jar_path
|
||||
|
||||
_proguard_preprocess =
|
||||
defined(invoker.proguard_preprocess) && invoker.proguard_preprocess
|
||||
|
||||
_jar_excluded_patterns = []
|
||||
if (defined(invoker.jar_excluded_patterns)) {
|
||||
_jar_excluded_patterns = invoker.jar_excluded_patterns
|
||||
|
@ -1019,24 +1021,15 @@ if (enable_java_templates) {
|
|||
invoker.strip_resource_classes
|
||||
_filter_jar = _jar_excluded_patterns != [] || _strip_resource_classes
|
||||
|
||||
if (_filter_jar) {
|
||||
_filter_target = "${target_name}__filter"
|
||||
_output_jar_target = _filter_target
|
||||
}
|
||||
if (_proguard_preprocess) {
|
||||
_proguard_target = "${target_name}__proguard_process"
|
||||
_output_jar_target = _proguard_target
|
||||
}
|
||||
if (!_filter_jar && !_proguard_preprocess) {
|
||||
_copy_target = "${target_name}__copy"
|
||||
_output_jar_target = _copy_target
|
||||
}
|
||||
_enable_assert =
|
||||
defined(invoker.supports_android) && invoker.supports_android &&
|
||||
(is_java_debug || dcheck_always_on)
|
||||
assert(_enable_assert || true) # Mark used.
|
||||
|
||||
if (_filter_jar) {
|
||||
_filtered_jar_path = _output_jar_path
|
||||
if (_proguard_preprocess) {
|
||||
_filtered_jar_path = "$target_out_dir/$target_name-filtered.jar"
|
||||
}
|
||||
_filter_target = "${target_name}__filter"
|
||||
|
||||
_filter_jar_path = "$target_out_dir/$target_name-filtered.jar"
|
||||
action(_filter_target) {
|
||||
script = "//build/android/gyp/jar.py"
|
||||
forward_variables_from(invoker,
|
||||
|
@ -1049,13 +1042,13 @@ if (enable_java_templates) {
|
|||
_input_jar_path,
|
||||
]
|
||||
outputs = [
|
||||
_filtered_jar_path,
|
||||
_filter_jar_path,
|
||||
]
|
||||
args = [
|
||||
"--input-jar",
|
||||
rebase_path(_input_jar_path, root_build_dir),
|
||||
"--jar-path",
|
||||
rebase_path(_filtered_jar_path, root_build_dir),
|
||||
rebase_path(_filter_jar_path, root_build_dir),
|
||||
"--excluded-classes=$_jar_excluded_patterns",
|
||||
]
|
||||
if (_strip_resource_classes) {
|
||||
|
@ -1065,31 +1058,34 @@ if (enable_java_templates) {
|
|||
}
|
||||
|
||||
if (_proguard_preprocess) {
|
||||
_output_jar_target = "${target_name}__proguard_process"
|
||||
_proguard_output_jar = _output_jar_path
|
||||
_proguard_config_path = invoker.proguard_preprocess_config
|
||||
proguard(_proguard_target) {
|
||||
proguard(_output_jar_target) {
|
||||
if (_filter_jar) {
|
||||
_proguard_input_jar = _filtered_jar_path
|
||||
public_deps = [
|
||||
_proguard_input_jar = _filter_jar_path
|
||||
deps = [
|
||||
":$_filter_target",
|
||||
]
|
||||
} else {
|
||||
_proguard_input_jar = _input_jar_path
|
||||
public_deps = []
|
||||
deps = []
|
||||
}
|
||||
if (defined(invoker.deps)) {
|
||||
deps = invoker.deps
|
||||
deps += invoker.deps
|
||||
}
|
||||
if (defined(invoker.public_deps)) {
|
||||
public_deps += invoker.public_deps
|
||||
public_deps = invoker.public_deps
|
||||
}
|
||||
inputs = [
|
||||
_build_config,
|
||||
_proguard_config_path,
|
||||
_proguard_input_jar,
|
||||
]
|
||||
output_jar_path = _output_jar_path
|
||||
output_jar_path = _proguard_output_jar
|
||||
|
||||
_rebased_input_paths = [ rebase_path(_input_jar_path, root_build_dir) ]
|
||||
_rebased_input_paths =
|
||||
[ rebase_path(_proguard_input_jar, root_build_dir) ]
|
||||
_rebased_proguard_configs =
|
||||
[ rebase_path(_proguard_config_path, root_build_dir) ]
|
||||
args = [
|
||||
|
@ -1098,15 +1094,60 @@ if (enable_java_templates) {
|
|||
"--classpath=@FileArg($_rebased_build_config:javac:classpath)",
|
||||
]
|
||||
}
|
||||
} else if (!_filter_jar) {
|
||||
copy(_copy_target) {
|
||||
forward_variables_from(invoker,
|
||||
[
|
||||
"deps",
|
||||
"public_deps",
|
||||
])
|
||||
} else if (_enable_assert) {
|
||||
_output_jar_target = "${target_name}__assert"
|
||||
_assert_output_jar = _output_jar_path
|
||||
action(_output_jar_target) {
|
||||
script = "$root_out_dir/bin/helper/java_assertion_enabler"
|
||||
if (_filter_jar) {
|
||||
_assert_input_jar = _filter_jar_path
|
||||
deps = [
|
||||
":$_filter_target",
|
||||
"//build/android/java_assertion_enabler",
|
||||
]
|
||||
} else {
|
||||
_assert_input_jar = _input_jar_path
|
||||
deps = [
|
||||
"//build/android/java_assertion_enabler",
|
||||
]
|
||||
}
|
||||
if (defined(invoker.deps)) {
|
||||
deps += invoker.deps
|
||||
}
|
||||
if (defined(invoker.public_deps)) {
|
||||
public_deps = invoker.public_deps
|
||||
}
|
||||
inputs = [
|
||||
_assert_input_jar,
|
||||
]
|
||||
outputs = [
|
||||
_assert_output_jar,
|
||||
]
|
||||
args = [
|
||||
rebase_path(_assert_input_jar, root_build_dir),
|
||||
rebase_path(_assert_output_jar, root_build_dir),
|
||||
]
|
||||
}
|
||||
} else {
|
||||
_output_jar_target = "${target_name}__copy"
|
||||
copy(_output_jar_target) {
|
||||
if (_filter_jar) {
|
||||
_copy_input_jar = _filter_jar_path
|
||||
public_deps = [
|
||||
":$_filter_target",
|
||||
]
|
||||
} else {
|
||||
_copy_input_jar = _input_jar_path
|
||||
public_deps = []
|
||||
}
|
||||
if (defined(invoker.deps)) {
|
||||
deps = invoker.deps
|
||||
}
|
||||
if (defined(invoker.public_deps)) {
|
||||
public_deps += invoker.public_deps
|
||||
}
|
||||
sources = [
|
||||
_input_jar_path,
|
||||
_copy_input_jar,
|
||||
]
|
||||
outputs = [
|
||||
_output_jar_path,
|
||||
|
@ -1802,6 +1843,7 @@ if (enable_java_templates) {
|
|||
visibility += [ ":$_dex_target_name" ]
|
||||
}
|
||||
|
||||
supports_android = _supports_android
|
||||
build_config = _build_config
|
||||
input_jar_path = invoker.jar_path
|
||||
output_jar_path = _jar_path
|
||||
|
@ -2093,6 +2135,7 @@ if (enable_java_templates) {
|
|||
"proguard_preprocess",
|
||||
"proguard_preprocess_config",
|
||||
])
|
||||
supports_android = _supports_android
|
||||
build_config = _build_config
|
||||
input_jar_path = _javac_jar_path
|
||||
output_jar_path = _process_prebuilt_jar_path
|
||||
|
|
Загрузка…
Ссылка в новой задаче