Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/dcmd/compiler/MethodIdentifierParser.java
41153 views
1
/*
2
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import java.lang.reflect.Method;
25
import java.util.ArrayList;
26
27
public class MethodIdentifierParser {
28
29
private String logString;
30
private String className;
31
private String methodName;
32
private String methodDescriptor;
33
34
/**
35
* This is a utility class for parsing the log entries for a method. It supplies
36
* a few select methods for reflecting the class and method from that information.
37
*
38
* Example log entries:
39
* "java.util.TreeMap.successor(Ljava/util/TreeMap$Entry;)Ljava/util/TreeMap$Entry;"
40
*/
41
42
public MethodIdentifierParser(String logString) {
43
this.logString = logString;
44
45
int i = logString.lastIndexOf("."); // find start of method name
46
className = logString.substring(0, i); // classname is everything before
47
int i2 = logString.indexOf("("); // Signature starts with an '('
48
methodName = logString.substring(i+1, i2);
49
methodDescriptor = logString.substring(i2, logString.length());
50
51
// Add sanity check for extracted fields
52
}
53
54
public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException {
55
try {
56
return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray());
57
} catch (UnexpectedTokenException e) {
58
throw new RuntimeException("Parse failed");
59
}
60
}
61
62
public Class<?>[] getParamenterDescriptorArray() throws ClassNotFoundException, UnexpectedTokenException {
63
ParameterDecriptorIterator s = new ParameterDecriptorIterator(methodDescriptor);
64
Class<?> paramType;
65
ArrayList<Class<?>> list = new ArrayList<Class<?>>();
66
while ((paramType = s.nextParamType()) != null) {
67
list.add(paramType);
68
}
69
if (list.size() > 0) {
70
return list.toArray(new Class<?>[list.size()]);
71
} else {
72
return null;
73
}
74
}
75
76
class ParameterDecriptorIterator {
77
78
// This class uses charAt() indexing for startMark and i
79
// That is when i points to the last char it can be retrieved with
80
// charAt(i). Including the last char for a subString requires
81
// substring(startMark, i+1);
82
83
private String methodDescriptor;
84
private int startMark;
85
86
public ParameterDecriptorIterator(String signature) {
87
this.methodDescriptor = signature;
88
this.startMark = 0;
89
if (signature.charAt(0) == '(') {
90
this.startMark = 1;
91
}
92
}
93
94
public Class<?> nextParamType() throws UnexpectedTokenException {
95
int i = startMark;
96
while (methodDescriptor.length() > i) {
97
switch (methodDescriptor.charAt(i)) {
98
case 'C':
99
case 'B':
100
case 'I':
101
case 'J':
102
case 'Z':
103
case 'F':
104
case 'D':
105
case 'S':
106
// Primitive class case, but we may have gotten here with [ as first token
107
break;
108
case 'L':
109
// Internal class name suffixed by ';'
110
while (methodDescriptor.charAt(i) != ';') {
111
i++;
112
}
113
break;
114
case '[':
115
i++; // arrays -> do another pass
116
continue;
117
case ')':
118
return null; // end found
119
case 'V':
120
case ';':
121
default:
122
throw new UnexpectedTokenException(methodDescriptor, i);
123
}
124
break;
125
}
126
if (i == startMark) {
127
// Single char -> primitive class case
128
startMark++; // Update for next iteration
129
switch (methodDescriptor.charAt(i)) {
130
case 'C':
131
return char.class;
132
case 'B':
133
return byte.class;
134
case 'I':
135
return int.class;
136
case 'J':
137
return long.class;
138
case 'F':
139
return float.class;
140
case 'D':
141
return double.class;
142
case 'S':
143
return short.class;
144
case 'Z':
145
return boolean.class;
146
default:
147
throw new UnexpectedTokenException(methodDescriptor, i);
148
}
149
} else {
150
// Multi char case
151
String nextParam;
152
if (methodDescriptor.charAt(startMark) == 'L') {
153
// When reflecting a class the leading 'L' and trailing';' must be removed.
154
// (When reflecting an array of classes, they must remain...)
155
nextParam = methodDescriptor.substring(startMark+1, i);
156
} else {
157
// Any kind of array - simple case, use whole descriptor when reflecting.
158
nextParam = methodDescriptor.substring(startMark, i+1);
159
}
160
startMark = ++i; // Update for next iteration
161
try {
162
// The parameter descriptor uses JVM internal class identifier with '/' as
163
// package separator, but Class.forName expects '.'.
164
nextParam = nextParam.replace('/', '.');
165
return Class.forName(nextParam);
166
} catch (ClassNotFoundException e) {
167
System.out.println("Class not Found: " + nextParam);
168
return null;
169
}
170
}
171
}
172
}
173
174
class UnexpectedTokenException extends Exception {
175
String descriptor;
176
int i;
177
public UnexpectedTokenException(String descriptor, int i) {
178
this.descriptor = descriptor;
179
this.i = i;
180
}
181
182
@Override
183
public String toString() {
184
return "Unexpected token at: " + i + " in signature: " + descriptor;
185
}
186
187
private static final long serialVersionUID = 1L;
188
}
189
190
public void debugPrint() {
191
System.out.println("mlf in: " + logString);
192
System.out.println("mlf class: " + className);
193
System.out.println("mlf method: " + methodName);
194
System.out.println("mlf methodDescriptor: " + methodDescriptor);
195
}
196
}
197
198