1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Anatoly F. Bondarenko 21 */ 22 23 /** 24 * Created on 24.02.2005 25 */ 26 package org.apache.harmony.jpda.tests.jdwp.ReferenceType; 27 28 import java.lang.reflect.Constructor; 29 import java.lang.reflect.Proxy; 30 import java.net.URLClassLoader; 31 import java.net.URL; 32 import java.nio.ByteBuffer; 33 import java.nio.file.Files; 34 import java.nio.file.Path; 35 import java.util.Base64; 36 37 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 38 import org.apache.harmony.jpda.tests.share.SyncDebuggee; 39 40 public class SourceDebugExtensionDebuggee extends SyncDebuggee { 41 42 private final static String classWithSourceDebugExtension = 43 "org.apache.harmony.jpda.tests.jdwp.Events.SourceDebugExtensionMockClass"; 44 45 private final static String inMemoryDexClassLoaderClass = 46 "dalvik.system.InMemoryDexClassLoader"; 47 48 /* 49 * A base64 string of a dex file built from the 50 * class packaged with apache-harmony for JSR45 testing: 51 * 52 * cd apache-harmony/jdwp/src/test/resources 53 * dx --dex --output=classes.dex \ 54 * org/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass.class 55 * 56 * This simplifies dealing with multiple dex files in the Android 57 * build system and with Jack which discards the JSR45 metadata. 58 */ 59 private final static String base64DexWithExtensionClass = 60 "ZGV4CjAzNQAktKYbHXK+eDSBH4IRfDw2pS8X3+CKeds0BAAAcAAAAHhWNBIAAAAAAAAAAHADAAAT" + 61 "AAAAcAAAAAgAAAC8AAAAAwAAANwAAAABAAAAAAEAAAQAAAAIAQAAAQAAACgBAADsAgAASAEAAKYB" + 62 "AACuAQAAuwEAAOUBAAD8AQAAEAIAACQCAAA4AgAAgwIAAOkCAAANAwAAEAMAABQDAAApAwAALwMA" + 63 "ADUDAAA6AwAAQwMAAEkDAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAKAAAADAAAAAoAAAAGAAAA" + 64 "AAAAAAsAAAAGAAAAmAEAAAsAAAAGAAAAoAEAAAQAAQAPAAAAAQABABAAAAACAAAAAAAAAAUAAAAA" + 65 "AAAABQACAA4AAAAFAAAAAQAAAAIAAAAAAAAACQAAAIgBAABiAwAAAAAAAAEAAABcAwAAAQABAAEA" + 66 "AABQAwAABAAAAHAQAQAAAA4AAwABAAIAAABVAwAACAAAAGIAAAAaAQEAbiAAABAADgBIAQAAAAAA" + 67 "AAAAAAAAAAAAAQAAAAMAAAABAAAABwAGPGluaXQ+AAtIZWxsbyBXb3JsZAAoTGRhbHZpay9hbm5v" + 68 "dGF0aW9uL1NvdXJjZURlYnVnRXh0ZW5zaW9uOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2" + 69 "YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AElM" + 70 "b3JnL2FwYWNoZS9oYXJtb255L2pwZGEvdGVzdHMvamR3cC9FdmVudHMvU291cmNlRGVidWdFeHRl" + 71 "bnNpb25Nb2NrQ2xhc3M7AGRTTUFQCmhlbGxvd29ybGRfanNwLmphdmEKSlNQCipTIEpTUAoqRgor" + 72 "IDAgaGVsbG93b3JsZC5qc3AKaGVsbG93b3JsZC5qc3AKKkwKMSw1OjUzCjY6NTgsMwo3LDQ6NjEK" + 73 "KkUKACJTb3VyY2VEZWJ1Z0V4dGVuc2lvbk1vY2tDbGFzcy5qYXZhAAFWAAJWTAATW0xqYXZhL2xh" + 74 "bmcvU3RyaW5nOwAEYXJncwAEbWFpbgADb3V0AAdwcmludGxuAAR0aGlzAAV2YWx1ZQADAAcOAAYB" + 75 "DgcOeAACAAESFwgAAAIAAoGABNACAQnoAhAAAAAAAAAAAQAAAAAAAAABAAAAEwAAAHAAAAACAAAA" + 76 "CAAAALwAAAADAAAAAwAAANwAAAAEAAAAAQAAAAABAAAFAAAABAAAAAgBAAAGAAAAAQAAACgBAAAD" + 77 "EAAAAQAAAEgBAAABIAAAAgAAAFABAAAGIAAAAQAAAIgBAAABEAAAAgAAAJgBAAACIAAAEwAAAKYB" + 78 "AAADIAAAAgAAAFADAAAEIAAAAQAAAFwDAAAAIAAAAQAAAGIDAAAAEAAAAQAAAHADAAA="; 79 80 /* 81 * A base64 string of a jar file containing: 82 * org/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass.class 83 */ 84 private final static String base64JarWithExtensionClass = 85 "UEsDBBQACAgIAAZwmUoAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAA" + 86 "AAAAAFBLAwQUAAgICAAGcJlKAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803M" + 87 "y0xLLS7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEm5jqZuaVpBblJeYoaPgXJSbnpCo4" + 88 "5xcV5BcllgD1afJy8XIBAFBLBwiUuAa1TAAAAE0AAABQSwMECgAACAAATYIRSQAAAAAAAAAAAAAA" + 89 "AAQAAABvcmcvUEsDBAoAAAgAAE2CEUkAAAAAAAAAAAAAAAALAAAAb3JnL2FwYWNoZS9QSwMECgAA" + 90 "CAAATYIRSQAAAAAAAAAAAAAAABMAAABvcmcvYXBhY2hlL2hhcm1vbnkvUEsDBAoAAAgAAE2CEUkA" + 91 "AAAAAAAAAAAAAAAYAAAAb3JnL2FwYWNoZS9oYXJtb255L2pwZGEvUEsDBAoAAAgAAE2CEUkAAAAA" + 92 "AAAAAAAAAAAeAAAAb3JnL2FwYWNoZS9oYXJtb255L2pwZGEvdGVzdHMvUEsDBAoAAAgAAE2CEUkA" + 93 "AAAAAAAAAAAAAAAjAAAAb3JnL2FwYWNoZS9oYXJtb255L2pwZGEvdGVzdHMvamR3cC9QSwMECgAA" + 94 "CAAAHUmYSgAAAAAAAAAAAAAAACoAAABvcmcvYXBhY2hlL2hhcm1vbnkvanBkYS90ZXN0cy9qZHdw" + 95 "L0V2ZW50cy9QSwMEFAAICAgATYIRSQAAAAAAAAAAAAAAAE0AAABvcmcvYXBhY2hlL2hhcm1vbnkv" + 96 "anBkYS90ZXN0cy9qZHdwL0V2ZW50cy9Tb3VyY2VEZWJ1Z0V4dGVuc2lvbk1vY2tDbGFzcy5jbGFz" + 97 "c61RTW/TQBB926Rxsg20JE35Brdc0hDVRCUtShASKikfciGSUThwQBt75TjYXst2Wvqz4AASB34A" + 98 "PwoxdipFoIgTe5i3M/tm9N7sz1/ffwDo4J6GFYbnKnYNEQl7Io2JiAMVnhvTyBFGKpM0MabOWWQM" + 99 "TmVId0vNYls+k+OZO/iUyjDxVHii7I9HvkgSDUWGjak4FYYvQtd4M55KO2UoPfZCL33CUGjujhiK" + 100 "R8qRHAVUqlhFiWHd9EL5ehaMZfxWjH3JUDOVLfyRiL0svygW04mXMLw0/5PcPo0MhBcybDXfmwvZ" + 101 "Vhp7odvfHVVwBXUNtT9MWedJKoMqNtEgQ2pG/hrzZk8ZQ+pMqV+KoF/GVYa1F9L3lf5Oxb7DcR03" + 102 "NdxgqC/hV3ELtxm0KCv5JKrRXKaJNIvYpTXUl0hm4HPHx162sJ1/2t/L2hk2l5GwDTKH7KzQjX6J" + 103 "okaZQcgIV1vfUP6cP3OKpbxYwBrF6pxAeImwgstYv2g+zIdR7Qs2altfcW0xgBNmY8pEXAyp4A7u" + 104 "5hw9j9vYIXSsk6dDPskWe5bt9cM0iXIz/JU15C1Lz+GY39cf6AvWHrH4X2nL5J12t9fd5we97qP2" + 105 "Pj9sP+wddHhrwH8DUEsHCFc9MsLTAQAAIwMAAFBLAQIUABQACAgIAAZwmUoAAAAAAgAAAAAAAAAJ" + 106 "AAQAAAAAAAAAAAAAAAAAAABNRVRBLUlORi/+ygAAUEsBAhQAFAAICAgABnCZSpS4BrVMAAAATQAA" + 107 "ABQAAAAAAAAAAAAAAAAAPQAAAE1FVEEtSU5GL01BTklGRVNULk1GUEsBAgoACgAACAAATYIRSQAA" + 108 "AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAywAAAG9yZy9QSwECCgAKAAAIAABNghFJAAAAAAAAAAAA" + 109 "AAAACwAAAAAAAAAAAAAAAADtAAAAb3JnL2FwYWNoZS9QSwECCgAKAAAIAABNghFJAAAAAAAAAAAA" + 110 "AAAAEwAAAAAAAAAAAAAAAAAWAQAAb3JnL2FwYWNoZS9oYXJtb255L1BLAQIKAAoAAAgAAE2CEUkA" + 111 "AAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAEcBAABvcmcvYXBhY2hlL2hhcm1vbnkvanBkYS9QSwEC" + 112 "CgAKAAAIAABNghFJAAAAAAAAAAAAAAAAHgAAAAAAAAAAAAAAAAB9AQAAb3JnL2FwYWNoZS9oYXJt" + 113 "b255L2pwZGEvdGVzdHMvUEsBAgoACgAACAAATYIRSQAAAAAAAAAAAAAAACMAAAAAAAAAAAAAAAAA" + 114 "uQEAAG9yZy9hcGFjaGUvaGFybW9ueS9qcGRhL3Rlc3RzL2pkd3AvUEsBAgoACgAACAAAHUmYSgAA" + 115 "AAAAAAAAAAAAACoAAAAAAAAAAAAAAAAA+gEAAG9yZy9hcGFjaGUvaGFybW9ueS9qcGRhL3Rlc3Rz" + 116 "L2pkd3AvRXZlbnRzL1BLAQIUABQACAgIAE2CEUlXPTLC0wEAACMDAABNAAAAAAAAAAAAAAAAAEIC" + 117 "AABvcmcvYXBhY2hlL2hhcm1vbnkvanBkYS90ZXN0cy9qZHdwL0V2ZW50cy9Tb3VyY2VEZWJ1Z0V4" + 118 "dGVuc2lvbk1vY2tDbGFzcy5jbGFzc1BLBQYAAAAACgAKAN8CAACQBAAAAAA="; 119 120 private ClassLoader getClassLoaderInitializedWithDexFile() { 121 try { 122 byte[] dexBytes = Base64.getDecoder().decode(base64DexWithExtensionClass); 123 ByteBuffer dexBuffer = ByteBuffer.wrap(dexBytes); 124 Class<?> klass = Class.forName(inMemoryDexClassLoaderClass); 125 Constructor<?> constructor = klass.getConstructor(ByteBuffer.class, ClassLoader.class); 126 return (ClassLoader) constructor.newInstance(dexBuffer, 127 ClassLoader.getSystemClassLoader()); 128 } catch (Exception e) { 129 logWriter.println("--> Debuggee: Failed to instantiate " + inMemoryDexClassLoaderClass 130 + " " + e); 131 return null; 132 } 133 } 134 135 private ClassLoader getClassLoaderInitializedWithClassFile() { 136 try { 137 byte[] jarBytes = Base64.getDecoder().decode(base64JarWithExtensionClass); 138 Path jarPath = Files.createTempFile(null, "jar"); 139 jarPath.toFile().deleteOnExit(); 140 Files.write(jarPath, jarBytes); 141 return new URLClassLoader(new URL[] { jarPath.toUri().toURL() }); 142 } catch (Exception e) { 143 logWriter.println("--> Debuggee: Failed to instantiate URLClassLoader: " + e); 144 return null; 145 } 146 } 147 148 @Override 149 public void run() { 150 ClassLoader classLoader = null; 151 if (System.getProperty("java.vendor").contains("Android")) { 152 classLoader = getClassLoaderInitializedWithDexFile(); 153 } else { 154 classLoader = getClassLoaderInitializedWithClassFile(); 155 } 156 157 Class<?> klass = null; 158 try { 159 klass = classLoader.loadClass(classWithSourceDebugExtension); 160 } catch (ClassNotFoundException e) { 161 logWriter.println("--> Debuggee: Could not find class " + 162 classWithSourceDebugExtension); 163 } 164 165 // Create an instance of classWithSourceDebugExtension so the 166 // SourceDebugExtension metadata can be reported back to the debugger. 167 Object o = null; 168 if (klass != null) { 169 try { 170 o = klass.getConstructor().newInstance(); 171 } catch (Exception e) { 172 logWriter.println("--> Debuggee: Failed to instantiate " + 173 classWithSourceDebugExtension + ": " + e); 174 } 175 } 176 177 // Instantiate a proxy whose name should contain "$Proxy". 178 Class proxy = Proxy.getProxyClass(SomeInterface.class.getClassLoader(), 179 new Class[] { SomeInterface.class }); 180 181 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY); 182 logWriter.println("--> Debuggee: SourceDebugExtensionDebuggee..."); 183 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 184 } 185 186 interface SomeInterface {} 187 188 public static void main(String [] args) { 189 runDebuggee(SourceDebugExtensionDebuggee.class); 190 } 191 192 } 193