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:
zpeng 2016-11-16 08:55:04 -08:00 коммит произвёл Commit bot
Родитель 0f22313e62
Коммит 9f06956677
3 изменённых файлов: 135 добавлений и 66 удалений

Просмотреть файл

@ -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 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);
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);
}
if (entry.isDirectory() || !entry.getName().endsWith(CLASS_FILE_SUFFIX)) {
outputStream.putNextEntry(entry);
outputStream.write(byteCode);
outputStream.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();
return buffer.toByteArray();
}
static void enableAssertionInJar(String inputJarPath, String outputJarPath) {
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)) {
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();
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