content: /*
   * Copyright (C) 2017 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  import dalvik.system.InMemoryDexClassLoader;
  
  import java.io.InputStream;
  import java.lang.reflect.Method;
  import java.nio.ByteBuffer;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipFile;
  
  public class Main {
  
    public static void main(String[] args) throws Exception {
      // Extract Dex file contents from the secondary Jar file.
      String jarFilename =
          System.getenv("DEX_LOCATION") + "/656-annotation-lookup-generic-jni-ex.jar";
      ZipFile zipFile = new ZipFile(jarFilename);
      ZipEntry zipEntry = zipFile.getEntry("classes.dex");
      InputStream inputStream = zipFile.getInputStream(zipEntry);
      int dexFileSize = (int) zipEntry.getSize();
      byte[] dexFileContents = new byte[dexFileSize];
      inputStream.read(dexFileContents, 0, dexFileSize);
  
      // Create class loader from secondary Dex file.
      ByteBuffer dexBuffer = ByteBuffer.wrap(dexFileContents);
      ClassLoader classLoader = createUnquickenedDexClassLoader(dexBuffer);
  
      // Load and initialize the Test class.
      Class<?> testClass = classLoader.loadClass("Test");
      Method initialize = testClass.getMethod("initialize", String.class);
      initialize.invoke(null, args[0]);
  
      // Invoke Test.nativeMethodWithAnnotation().
      Method nativeMethodWithAnnotation = testClass.getMethod("nativeMethodWithAnnotation");
      // Invoking the native method Test.nativeMethodWithAnnotation used
      // to crash the Generic JNI trampoline during the resolution of
      // the method's annotations (DummyAnnotation) (see b/38454151).
      nativeMethodWithAnnotation.invoke(null);
  
      zipFile.close();
      System.out.println("passed");
    }
  
    // Create a class loader loading a Dex file in memory
    // *without creating an Oat file*. This way, the Dex file won't be
    // quickened and JNI stubs won't be compiled, thus forcing the use
    // of Generic JNI when invoking the native method
    // Test.nativeMethodWithAnnotation.
    static ClassLoader createUnquickenedDexClassLoader(ByteBuffer dexBuffer) {
      InMemoryDexClassLoader cl = new InMemoryDexClassLoader(dexBuffer, getBootClassLoader());
      return cl;
    }
  
    static ClassLoader getBootClassLoader() {
      ClassLoader cl = Main.class.getClassLoader();
      while (cl.getParent() != null) {
        cl = cl.getParent();
      }
      return cl;
    }
  
  }
  