1 // Copyright (C) 2017 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 import java.lang.reflect.Method;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 
18 public class Main {
19 
20   static class OatMethodAndOffset implements Comparable<OatMethodAndOffset> {
21     Method method;
22     long codeOffset;
23 
OatMethodAndOffset(Method method, long codeOffset)24     public OatMethodAndOffset(Method method, long codeOffset) {
25       this.method = method;
26       this.codeOffset = codeOffset;
27     }
28 
29     // e.g. "Foo::Bar()"
methodReferenceString()30     public String methodReferenceString() {
31       return method.getDeclaringClass().getName() + "::" + method.getName();
32     }
33 
34     @Override
compareTo(OatMethodAndOffset other)35     public int compareTo(OatMethodAndOffset other) {
36       return Long.compareUnsigned(codeOffset, other.codeOffset);
37     }
38   }
39 
40   // Print the list of methods in Generated.class, sorted by their OAT code address.
main(String[] args)41   public static void main(String[] args) {
42     System.loadLibrary(args[0]);
43 
44     // Make sure to check "Test.class" because Main.class still has JNI which could be compiled
45     // even if the rest of the classes are not.
46     if (!hasOatCompiledCode(Test.class)) {
47       System.out.println("No OAT class");
48       return;
49     }
50 
51     // We only care about explicitly defined methods from Generated.java.
52     Method[] interesting_methods;
53     try {
54       interesting_methods = Test.getTestMethods();
55     } catch (NoSuchMethodException e) {
56       e.printStackTrace();
57       return;
58     }
59 
60     // Get the list of oat code methods for each Java method.
61     ArrayList<OatMethodAndOffset> offsets_list = new ArrayList<OatMethodAndOffset>();
62     for (Method m : interesting_methods) {
63       offsets_list.add(new OatMethodAndOffset(m, getOatMethodQuickCode(m)));
64     }
65 
66     // Sort by the offset address.
67     Collections.sort(offsets_list);
68 
69     // Print each method as a method reference string.
70     for (OatMethodAndOffset m : offsets_list) {
71       System.out.println(m.methodReferenceString());
72     }
73   }
74 
75   // Does Main.class have an OatClass with actually compiled code?
hasOatCompiledCode(Class kls)76   private static native boolean hasOatCompiledCode(Class kls);
77   // Get the OatMethod's pointer to code. We get 'real' memory address, not relative offset,
78   // but it's still good since we never compare multiple OAT files here.
getOatMethodQuickCode(Method method)79   private static native long getOatMethodQuickCode(Method method);
80 }
81