Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/langtools/tools/javac/7003595/T7003595.java
41152 views
1
/*
2
* Copyright (c) 2011, 2015, 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
/*
25
* @test
26
* @bug 7003595
27
* @summary IncompatibleClassChangeError with unreferenced local class with subclass
28
* @modules jdk.jdeps/com.sun.tools.classfile
29
* jdk.compiler/com.sun.tools.javac.api
30
* jdk.compiler/com.sun.tools.javac.file
31
*/
32
33
import com.sun.source.util.JavacTask;
34
import com.sun.tools.classfile.Attribute;
35
import com.sun.tools.classfile.ClassFile;
36
import com.sun.tools.classfile.InnerClasses_attribute;
37
import com.sun.tools.classfile.ConstantPool.*;
38
import com.sun.tools.javac.api.JavacTool;
39
40
import java.io.File;
41
import java.net.URI;
42
import java.util.Arrays;
43
import java.util.ArrayList;
44
import javax.tools.JavaCompiler;
45
import javax.tools.JavaFileObject;
46
import javax.tools.SimpleJavaFileObject;
47
import javax.tools.StandardJavaFileManager;
48
import javax.tools.ToolProvider;
49
50
51
public class T7003595 {
52
53
/** global decls ***/
54
55
//statistics
56
static int checkCount = 0;
57
58
enum ClassKind {
59
NESTED("static class #N { #B }", "$", true),
60
INNER("class #N { #B }", "$", false),
61
LOCAL_REF("void test() { class #N { #B }; new #N(); }", "$1", false),
62
LOCAL_NOREF("void test() { class #N { #B }; }", "$1", false),
63
ANON("void test() { new Object() { #B }; }", "$1", false),
64
NONE("", "", false);
65
66
String memberInnerStr;
67
String sep;
68
boolean staticAllowed;
69
70
private ClassKind(String memberInnerStr, String sep, boolean staticAllowed) {
71
this.memberInnerStr = memberInnerStr;
72
this.sep = sep;
73
this.staticAllowed = staticAllowed;
74
}
75
76
String getSource(String className, String outerName, String nested) {
77
return memberInnerStr.replaceAll("#O", outerName).
78
replaceAll("#N", className).replaceAll("#B", nested);
79
}
80
81
static String getClassfileName(String[] names, ClassKind[] outerKinds, int pos) {
82
System.out.println(" pos = " + pos + " kind = " + outerKinds[pos] + " sep = " + outerKinds[pos].sep);
83
String name = outerKinds[pos] != ANON ?
84
names[pos] : "";
85
if (pos == 0) {
86
return "Test" + outerKinds[pos].sep + name;
87
} else {
88
String outerStr = getClassfileName(names, outerKinds, pos - 1);
89
return outerStr + outerKinds[pos].sep + name;
90
}
91
}
92
93
boolean isAllowed(ClassKind nestedKind) {
94
return nestedKind != NESTED ||
95
staticAllowed;
96
}
97
}
98
99
enum LocalInnerClass {
100
LOCAL_REF("class L {}; new L();", "Test$1L"),
101
LOCAL_NOREF("class L {};", "Test$1L"),
102
ANON("new Object() {};", "Test$1"),
103
NONE("", "");
104
105
String localInnerStr;
106
String canonicalInnerStr;
107
108
private LocalInnerClass(String localInnerStr, String canonicalInnerStr) {
109
this.localInnerStr = localInnerStr;
110
this.canonicalInnerStr = canonicalInnerStr;
111
}
112
}
113
114
public static void main(String... args) throws Exception {
115
// Create a single file manager and reuse it for each compile to save time.
116
try (StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null)) {
117
for (ClassKind ck1 : ClassKind.values()) {
118
String cname1 = "C1";
119
for (ClassKind ck2 : ClassKind.values()) {
120
if (!ck1.isAllowed(ck2)) continue;
121
String cname2 = "C2";
122
for (ClassKind ck3 : ClassKind.values()) {
123
if (!ck2.isAllowed(ck3)) continue;
124
String cname3 = "C3";
125
new T7003595(fm, new ClassKind[] {ck1, ck2, ck3}, new String[] { cname1, cname2, cname3 }).compileAndCheck();
126
}
127
}
128
}
129
}
130
131
System.out.println("Total checks made: " + checkCount);
132
}
133
134
/** instance decls **/
135
136
ClassKind[] cks;
137
String[] cnames;
138
StandardJavaFileManager fm;
139
140
T7003595(StandardJavaFileManager fm, ClassKind[] cks, String[] cnames) {
141
this.fm = fm;
142
this.cks = cks;
143
this.cnames = cnames;
144
}
145
146
void compileAndCheck() throws Exception {
147
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
148
JavaSource source = new JavaSource();
149
JavacTask ct = (JavacTask)tool.getTask(null, fm, null,
150
null, null, Arrays.asList(source));
151
ct.call();
152
verifyBytecode(source);
153
}
154
155
void verifyBytecode(JavaSource source) {
156
for (int i = 0; i < 3 ; i ++) {
157
if (cks[i] == ClassKind.NONE) break;
158
checkCount++;
159
String filename = cks[i].getClassfileName(cnames, cks, i);
160
File compiledTest = new File(filename + ".class");
161
try {
162
ClassFile cf = ClassFile.read(compiledTest);
163
if (cf == null) {
164
throw new Error("Classfile not found: " + filename);
165
}
166
167
InnerClasses_attribute innerClasses = (InnerClasses_attribute)cf.getAttribute(Attribute.InnerClasses);
168
169
ArrayList<String> foundInnerSig = new ArrayList<>();
170
if (innerClasses != null) {
171
for (InnerClasses_attribute.Info info : innerClasses.classes) {
172
String foundSig = info.getInnerClassInfo(cf.constant_pool).getName();
173
foundInnerSig.add(foundSig);
174
}
175
}
176
177
ArrayList<String> expectedInnerSig = new ArrayList<>();
178
//add inner class (if any)
179
if (i < 2 && cks[i + 1] != ClassKind.NONE) {
180
expectedInnerSig.add(cks[i + 1].getClassfileName(cnames, cks, i + 1));
181
}
182
//add inner classes
183
for (int j = 0 ; j != i + 1 && j < 3; j++) {
184
expectedInnerSig.add(cks[j].getClassfileName(cnames, cks, j));
185
}
186
187
if (expectedInnerSig.size() != foundInnerSig.size()) {
188
throw new Error("InnerClasses attribute for " + cnames[i] + " has wrong size\n" +
189
"expected " + expectedInnerSig.size() + "\n" +
190
"found " + innerClasses.number_of_classes + "\n" +
191
source);
192
}
193
194
for (String foundSig : foundInnerSig) {
195
if (!expectedInnerSig.contains(foundSig)) {
196
throw new Error("InnerClasses attribute for " + cnames[i] + " has unexpected signature: " +
197
foundSig + "\n" + source + "\n" + expectedInnerSig);
198
}
199
}
200
201
for (String expectedSig : expectedInnerSig) {
202
if (!foundInnerSig.contains(expectedSig)) {
203
throw new Error("InnerClasses attribute for " + cnames[i] + " does not contain expected signature: " +
204
expectedSig + "\n" + source);
205
}
206
}
207
} catch (Exception e) {
208
e.printStackTrace();
209
throw new Error("error reading " + compiledTest +": " + e);
210
}
211
}
212
}
213
214
class JavaSource extends SimpleJavaFileObject {
215
216
static final String source_template = "class Test { #C }";
217
218
String source;
219
220
public JavaSource() {
221
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
222
String c3 = cks[2].getSource(cnames[2], cnames[1], "");
223
String c2 = cks[1].getSource(cnames[1], cnames[0], c3);
224
String c1 = cks[0].getSource(cnames[0], "Test", c2);
225
source = source_template.replace("#C", c1);
226
}
227
228
@Override
229
public String toString() {
230
return source;
231
}
232
233
@Override
234
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
235
return source;
236
}
237
}
238
}
239
240