Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(341)

Side by Side Diff: build/android/java_assertion_enabler/java/org/chromium/javaassertionenabler/AssertionEnabler.java

Issue 2971063003: Handle Java assert using a customized function in base (Closed)
Patch Set: just refactor, do not report exception Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.javaassertionenabler; 5 package org.chromium.javaassertionenabler;
6 6
7 import org.objectweb.asm.ClassReader; 7 import org.objectweb.asm.ClassReader;
8 import org.objectweb.asm.ClassVisitor; 8 import org.objectweb.asm.ClassVisitor;
9 import org.objectweb.asm.ClassWriter; 9 import org.objectweb.asm.ClassWriter;
10 import org.objectweb.asm.MethodVisitor; 10 import org.objectweb.asm.MethodVisitor;
11 import org.objectweb.asm.Opcodes; 11 import org.objectweb.asm.Opcodes;
12 12
13 import java.io.BufferedInputStream; 13 import java.io.BufferedInputStream;
14 import java.io.BufferedOutputStream; 14 import java.io.BufferedOutputStream;
15 import java.io.ByteArrayOutputStream; 15 import java.io.ByteArrayOutputStream;
16 import java.io.FileInputStream; 16 import java.io.FileInputStream;
17 import java.io.FileOutputStream; 17 import java.io.FileOutputStream;
18 import java.io.IOException; 18 import java.io.IOException;
19 import java.io.InputStream; 19 import java.io.InputStream;
20 import java.nio.file.Files; 20 import java.nio.file.Files;
21 import java.nio.file.Path; 21 import java.nio.file.Path;
22 import java.nio.file.Paths; 22 import java.nio.file.Paths;
23 import java.nio.file.StandardCopyOption; 23 import java.nio.file.StandardCopyOption;
24 import java.util.zip.ZipEntry; 24 import java.util.zip.ZipEntry;
25 import java.util.zip.ZipInputStream; 25 import java.util.zip.ZipInputStream;
26 import java.util.zip.ZipOutputStream; 26 import java.util.zip.ZipOutputStream;
27 27
28 /** 28 /**
29 * An application that enables Java ASSERT statements by modifying Java bytecode . It takes in a JAR 29 * An application that replace Java ASSERT statements with a function by modifyi ng Java bytecode. It
30 * file, modifies bytecode of classes that use ASSERT, and outputs the bytecode to a new JAR file. 30 * takes in a JAR file, modifies bytecode of classes that use ASSERT, and output s the bytecode to a
31 * new JAR file.
32 * First enable assert:
33 * The following bytecode is generated for each class with ASSERT statements:
34 * 0: ldc #8 // class CLASSNAME
35 * 2: invokevirtual #9 // Method java/lang/Class.desiredAssertionStatus:()Z
36 * 5: ifne 12
37 * 8: iconst_1
38 * 9: goto 13
39 * 12: iconst_0
40 * 13: putstatic #2 // Field $assertionsDisabled:Z
41 * Replaces line #13 to the following:
42 * 13: pop
43 * Consequently, $assertionsDisabled is assigned the default value FALSE.
44 *
45 * To replace assert statement with a function:
46 * The followed instructions are generated by a java assert statement:
47 * getstatic #3 // Field $assertionsDisabled:Z
48 * ...
49 * ifne 19
50 * new #4 // class java/lang/AssertionError
51 * dup
52 * ldc #5 // String (don't have this line if no asser t message given)
53 * invokespecial #6 // Method java/lang/AssertionError.
54 * athrow
55 * We replace athrow with a call to a function that handles the AssertionError.
31 */ 56 */
32 class AssertionEnabler { 57 class AssertionEnabler {
33 static final String ASSERTION_DISABLED_NAME = "$assertionsDisabled";
34 static final String CLASS_FILE_SUFFIX = ".class"; 58 static final String CLASS_FILE_SUFFIX = ".class";
35 static final String STATIC_INITIALIZER_NAME = "<clinit>";
36 static final String TEMPORARY_FILE_SUFFIX = ".temp"; 59 static final String TEMPORARY_FILE_SUFFIX = ".temp";
37
38 static final int BUFFER_SIZE = 16384; 60 static final int BUFFER_SIZE = 16384;
39 61
40 static class AssertionEnablerVisitor extends ClassVisitor { 62 static class AssertionEnablerVisitor extends ClassVisitor {
41 AssertionEnablerVisitor(ClassWriter writer) { 63 AssertionEnablerVisitor(ClassWriter writer) {
42 super(Opcodes.ASM5, writer); 64 super(Opcodes.ASM5, writer);
43 } 65 }
44 66
45 @Override 67 @Override
46 public MethodVisitor visitMethod(final int access, final String name, St ring desc, 68 public MethodVisitor visitMethod(final int access, final String name, St ring desc,
47 String signature, String[] exceptions) { 69 String signature, String[] exceptions) {
48 // Patch static initializer. 70 return new RewriteAssertMethodVisitorWriter(
49 if ((access & Opcodes.ACC_STATIC) != 0 && name.equals(STATIC_INITIAL IZER_NAME)) { 71 Opcodes.ASM5, super.visitMethod(access, name, desc, signatur e, exceptions)) {};
50 return new MethodVisitor(Opcodes.ASM5,
51 super.visitMethod(access, name, desc, signature, excepti ons)) {
52 // The following bytecode is generated for each class with A SSERT statements:
53 // 0: ldc #8 // class CLASSNAME
54 // 2: invokevirtual #9 // Method java/lang/Class.desiredAsse rtionStatus:()Z
55 // 5: ifne 12
56 // 8: iconst_1
57 // 9: goto 13
58 // 12: iconst_0
59 // 13: putstatic #2 // Field $assertionsDisabled:Z
60 //
61 // This function replaces line #13 to the following:
62 // 13: pop
63 // Consequently, $assertionsDisabled is assigned the default value FALSE.
64 @Override
65 public void visitFieldInsn(int opcode, String owner, String name, String desc) {
66 if (opcode == Opcodes.PUTSTATIC && name.equals(ASSERTION _DISABLED_NAME)) {
67 mv.visitInsn(Opcodes.POP);
68 } else {
69 super.visitFieldInsn(opcode, owner, name, desc);
70 }
71 }
72 };
73 }
74 return super.visitMethod(access, name, desc, signature, exceptions);
75 } 72 }
76 } 73 }
77 74
75 static class RewriteAssertMethodVisitorWriter extends MethodVisitor {
76 static final String ASSERTION_DISABLED_NAME = "$assertionsDisabled";
77 static final String INSERT_INSTRUCTION_OWNER = "org/chromium/base/JavaEx ceptionReporter";
78 static final String INSERT_INSTRUCTION_NAME = "assertFailureHandler";
79 static final String INSERT_INSTRUCTION_DESC = "(Ljava/lang/AssertionErro r;)V";
80 static final boolean INSERT_INSTRUCTION_ITF = false;
81
82 boolean mStartLoadingAssert;
83
84 public RewriteAssertMethodVisitorWriter(int api, MethodVisitor mv) {
85 super(api, mv);
86 }
87
88 @Override
89 public void visitFieldInsn(int opcode, String owner, String name, String desc) {
90 if (opcode == Opcodes.PUTSTATIC && name.equals(ASSERTION_DISABLED_NA ME)) {
91 super.visitInsn(Opcodes.POP); // enable assert
92 } else if (opcode == Opcodes.GETSTATIC && name.equals(ASSERTION_DISA BLED_NAME)) {
93 mStartLoadingAssert = true;
94 super.visitFieldInsn(opcode, owner, name, desc);
95 } else {
96 super.visitFieldInsn(opcode, owner, name, desc);
97 }
98 }
99
100 @Override
101 public void visitInsn(int opcode) {
102 if (!mStartLoadingAssert || opcode != Opcodes.ATHROW) {
103 super.visitInsn(opcode);
104 } else {
105 super.visitMethodInsn(Opcodes.INVOKESTATIC, INSERT_INSTRUCTION_O WNER,
106 INSERT_INSTRUCTION_NAME, INSERT_INSTRUCTION_DESC, INSERT _INSTRUCTION_ITF);
107 mStartLoadingAssert = false;
108 }
109 }
110 }
111
78 static byte[] readAllBytes(InputStream inputStream) throws IOException { 112 static byte[] readAllBytes(InputStream inputStream) throws IOException {
79 ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 113 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
80 int numRead = 0; 114 int numRead = 0;
81 byte[] data = new byte[BUFFER_SIZE]; 115 byte[] data = new byte[BUFFER_SIZE];
82 while ((numRead = inputStream.read(data, 0, data.length)) != -1) { 116 while ((numRead = inputStream.read(data, 0, data.length)) != -1) {
83 buffer.write(data, 0, numRead); 117 buffer.write(data, 0, numRead);
84 } 118 }
85
86 return buffer.toByteArray(); 119 return buffer.toByteArray();
87 } 120 }
88 121
89 static void enableAssertionInJar(String inputJarPath, String outputJarPath) { 122 static void enableAssertionInJar(String inputJarPath, String outputJarPath) {
90 String tempJarPath = outputJarPath + TEMPORARY_FILE_SUFFIX; 123 String tempJarPath = outputJarPath + TEMPORARY_FILE_SUFFIX;
91 try (ZipInputStream inputStream = new ZipInputStream( 124 try (ZipInputStream inputStream = new ZipInputStream(
92 new BufferedInputStream(new FileInputStream(inputJarPath))); 125 new BufferedInputStream(new FileInputStream(inputJarPath))) ;
93 ZipOutputStream tempStream = new ZipOutputStream( 126 ZipOutputStream tempStream = new ZipOutputStream(
94 new BufferedOutputStream(new FileOutputStream(tempJarPath))) ) { 127 new BufferedOutputStream(new FileOutputStream(tempJarPat h)))) {
95 ZipEntry entry = null; 128 ZipEntry entry = null;
96 129
97 while ((entry = inputStream.getNextEntry()) != null) { 130 while ((entry = inputStream.getNextEntry()) != null) {
98 byte[] byteCode = readAllBytes(inputStream); 131 byte[] byteCode = readAllBytes(inputStream);
99 132
100 if (entry.isDirectory() || !entry.getName().endsWith(CLASS_FILE_ SUFFIX)) { 133 if (entry.isDirectory() || !entry.getName().endsWith(CLASS_FILE_ SUFFIX)) {
101 tempStream.putNextEntry(entry); 134 tempStream.putNextEntry(entry);
102 tempStream.write(byteCode); 135 tempStream.write(byteCode);
103 tempStream.closeEntry(); 136 tempStream.closeEntry();
104 continue; 137 continue;
(...skipping 21 matching lines...) Expand all
126 159
127 public static void main(String[] args) { 160 public static void main(String[] args) {
128 if (args.length != 2) { 161 if (args.length != 2) {
129 System.out.println("Incorrect number of arguments."); 162 System.out.println("Incorrect number of arguments.");
130 System.out.println("Example usage: java_assertion_enabler input.jar output.jar"); 163 System.out.println("Example usage: java_assertion_enabler input.jar output.jar");
131 System.exit(-1); 164 System.exit(-1);
132 } 165 }
133 enableAssertionInJar(args[0], args[1]); 166 enableAssertionInJar(args[0], args[1]);
134 } 167 }
135 } 168 }
OLDNEW
« build/android/java_assertion_enabler/OWNERS ('K') | « build/android/java_assertion_enabler/OWNERS ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698