1// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2// for details. All rights reserved. Use of this source code is governed by a 3// BSD-style license that can be found in the LICENSE file. 4 5package com.android.tools.r8.regress; 6 7import static org.junit.Assert.assertEquals; 8import static org.junit.Assert.assertNull; 9import static org.junit.Assert.assertTrue; 10 11import com.android.tools.r8.D8Command; 12import com.android.tools.r8.ToolHelper; 13import com.android.tools.r8.smali.SmaliTestBase; 14import com.android.tools.r8.utils.AndroidApp; 15import com.android.tools.r8.utils.DexInspector; 16import com.android.tools.r8.utils.DexInspector.ClassSubject; 17import java.util.Base64; 18import java.util.List; 19import org.junit.Test; 20 21public class Regress37740372 extends SmaliTestBase { 22 23 /* 24 Binary class file data for a java.lang.Object stub implementation. Runnong javap -c on the 25 bytecode produces the following output: 26 27 Compiled from "Object.java" 28 public class java.lang.Object { 29 public java.lang.Object(); 30 Code: 31 0: new #1 // class java/lang/RuntimeException 32 3: dup 33 4: ldc #2 // String Stub! 34 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 35 9: athrow 36 37 protected java.lang.Object clone() throws java.lang.CloneNotSupportedException; 38 Code: 39 0: new #1 // class java/lang/RuntimeException 40 3: dup 41 4: ldc #2 // String Stub! 42 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 43 9: athrow 44 45 public boolean equals(java.lang.Object); 46 Code: 47 0: new #1 // class java/lang/RuntimeException 48 3: dup 49 4: ldc #2 // String Stub! 50 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 51 9: athrow 52 53 protected void finalize() throws java.lang.Throwable; 54 Code: 55 0: new #1 // class java/lang/RuntimeException 56 3: dup 57 4: ldc #2 // String Stub! 58 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 59 9: athrow 60 61 public final native java.lang.Class<?> getClass(); 62 63 public native int hashCode(); 64 65 public final native void notify(); 66 67 public final native void notifyAll(); 68 69 public java.lang.String toString(); 70 Code: 71 0: new #1 // class java/lang/RuntimeException 72 3: dup 73 4: ldc #2 // String Stub! 74 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 75 9: athrow 76 77 public final void wait() throws java.lang.InterruptedException; 78 Code: 79 0: new #1 // class java/lang/RuntimeException 80 3: dup 81 4: ldc #2 // String Stub! 82 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 83 9: athrow 84 85 public final void wait(long) throws java.lang.InterruptedException; 86 Code: 87 0: new #1 // class java/lang/RuntimeException 88 3: dup 89 4: ldc #2 // String Stub! 90 6: invokespecial #3 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V 91 9: athrow 92 93 public final native void wait(long, int) throws java.lang.InterruptedException; 94 } 95 */ 96 String javaLangObjectClassFile = 97 "yv66vgAAADEALwcAJwgAKAoAAQApBwAqAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1i" + 98 "ZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABJMamF2YS9sYW5nL09iamVjdDsB" + 99 "AAVjbG9uZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQAKRXhjZXB0aW9ucwcAKwEABmVxdWFscwEA" + 100 "FShMamF2YS9sYW5nL09iamVjdDspWgEAAW8BAAhmaW5hbGl6ZQcALAEACGdldENsYXNzAQATKClM" + 101 "amF2YS9sYW5nL0NsYXNzOwEACVNpZ25hdHVyZQEAFigpTGphdmEvbGFuZy9DbGFzczwqPjsBAAho" + 102 "YXNoQ29kZQEAAygpSQEABm5vdGlmeQEACW5vdGlmeUFsbAEACHRvU3RyaW5nAQAUKClMamF2YS9s" + 103 "YW5nL1N0cmluZzsBAAR3YWl0BwAtAQAEKEopVgEABm1pbGxpcwEAAUoBAAUoSkkpVgEAClNvdXJj" + 104 "ZUZpbGUBAAtPYmplY3QuamF2YQEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uAQAFU3R1YiEM" + 105 "AAUALgEAEGphdmEvbGFuZy9PYmplY3QBACRqYXZhL2xhbmcvQ2xvbmVOb3RTdXBwb3J0ZWRFeGNl" + 106 "cHRpb24BABNqYXZhL2xhbmcvVGhyb3dhYmxlAQAeamF2YS9sYW5nL0ludGVycnVwdGVkRXhjZXB0" + 107 "aW9uAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEABAAAAAAAAAAMAAEABQAGAAEABwAAADQAAwAB" + 108 "AAAACrsAAVkSArcAA78AAAACAAgAAAAGAAEAAAAEAAkAAAAMAAEAAAAKAAoACwAAAAQADAANAAIA" + 109 "BwAAADQAAwABAAAACrsAAVkSArcAA78AAAACAAgAAAAGAAEAAAAFAAkAAAAMAAEAAAAKAAoACwAA" + 110 "AA4AAAAEAAEADwABABAAEQABAAcAAAA+AAMAAgAAAAq7AAFZEgK3AAO/AAAAAgAIAAAABgABAAAA" + 111 "BgAJAAAAFgACAAAACgAKAAsAAAAAAAoAEgALAAEABAATAAYAAgAHAAAANAADAAEAAAAKuwABWRIC" + 112 "twADvwAAAAIACAAAAAYAAQAAAAcACQAAAAwAAQAAAAoACgALAAAADgAAAAQAAQAUAREAFQAWAAEA" + 113 "FwAAAAIAGAEBABkAGgAAAREAGwAGAAABEQAcAAYAAAABAB0AHgABAAcAAAA0AAMAAQAAAAq7AAFZ" + 114 "EgK3AAO/AAAAAgAIAAAABgABAAAADAAJAAAADAABAAAACgAKAAsAAAARAB8ABgACAAcAAAA0AAMA" + 115 "AQAAAAq7AAFZEgK3AAO/AAAAAgAIAAAABgABAAAADQAJAAAADAABAAAACgAKAAsAAAAOAAAABAAB" + 116 "ACAAEQAfACEAAgAHAAAAPgADAAMAAAAKuwABWRICtwADvwAAAAIACAAAAAYAAQAAAA4ACQAAABYA" + 117 "AgAAAAoACgALAAAAAAAKACIAIwABAA4AAAAEAAEAIAERAB8AJAABAA4AAAAEAAEAIAABACUAAAAC" + 118 "ACY="; 119 120 private void assertIsJavaLangObjet(ClassSubject clazz) { 121 assertTrue(clazz.getOriginalDescriptor().equals("Ljava/lang/Object;")); 122 assertNull(clazz.getDexClass().superType); 123 } 124 125 private void checkApplicationOnlyHasJavaLangObject(AndroidApp app) throws Throwable { 126 DexInspector inspector = new DexInspector(app); 127 inspector.forAllClasses(this::assertIsJavaLangObjet); 128 } 129 130 @Test 131 public void test() throws Throwable { 132 // Build an application with the java.lang.Object stub from a class file. 133 AndroidApp output = 134 ToolHelper.runD8( 135 D8Command.builder() 136 .addClassProgramData(Base64.getDecoder().decode(javaLangObjectClassFile)) 137 .build()); 138 checkApplicationOnlyHasJavaLangObject(output); 139 140 // Build an application with the java.lang.Object stub from a dex file. 141 List<byte[]> dex = output.writeToMemory(); 142 assertEquals(1, dex.size()); 143 checkApplicationOnlyHasJavaLangObject( 144 ToolHelper.runD8(D8Command.builder().addDexProgramData(dex).build())); 145 } 146} 147