Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java
41159 views
1
/*
2
* Copyright (c) 2014, 2018, 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
package gc.g1.unloading;
25
26
import java.io.File;
27
import java.io.FileOutputStream;
28
import java.io.IOException;
29
import java.nio.file.FileVisitResult;
30
import java.nio.file.FileVisitor;
31
import java.nio.file.Files;
32
import java.nio.file.Path;
33
import java.nio.file.Paths;
34
import java.nio.file.attribute.BasicFileAttributes;
35
import java.util.ArrayList;
36
import java.util.Arrays;
37
import java.util.List;
38
import java.util.jar.JarEntry;
39
import java.util.jar.JarOutputStream;
40
import java.util.jar.Manifest;
41
import javax.tools.JavaCompiler;
42
import javax.tools.JavaFileObject;
43
import javax.tools.StandardJavaFileManager;
44
import javax.tools.ToolProvider;
45
import jdk.internal.org.objectweb.asm.ClassReader;
46
import jdk.internal.org.objectweb.asm.ClassVisitor;
47
import jdk.internal.org.objectweb.asm.ClassWriter;
48
import jdk.internal.org.objectweb.asm.Opcodes;
49
50
/**
51
* Class that imitates shell script to produce jar file with many similar
52
* classes inside.
53
*
54
* The class generates sources, compiles the first one, applies magic of ASM
55
* to multiply classes and packs into classPool.jar
56
*
57
* Generation template is supposed to be ClassNNN.java.template
58
*/
59
public class GenClassPoolJar {
60
61
private final String templateFile;
62
private final String destDir;
63
private final int count;
64
65
private final File tmpArea;
66
private final File pkgDir;
67
68
private static final String JAR_NAME = "classPool.jar";
69
private static final String PKG_DIR_NAME = "gc/g1/unloading/rootSetHelper/classesPool";
70
71
public static void main(String args[]) {
72
new GenClassPoolJar(args).script();
73
}
74
75
/**
76
* Creates generator and parses command line args.
77
* @param args command line args
78
*/
79
public GenClassPoolJar(String args[]) {
80
if (args.length != 3) {
81
System.err.println("Usage:");
82
System.err.println("java " + GenClassPoolJar.class.getCanonicalName() +
83
" <template-file> <ouput-dir> <count>" );
84
throw new Error("Illegal number of parameters");
85
}
86
templateFile = args[0];
87
destDir = args[1];
88
count = Integer.parseInt(args[2]);
89
90
tmpArea = new File(destDir, "tmp-area");
91
pkgDir = new File(tmpArea, PKG_DIR_NAME);
92
93
}
94
/**
95
* Does everything.
96
*/
97
public void script() {
98
long startTime = System.currentTimeMillis();
99
System.out.println("Trying to produce: " + destDir + "/" + JAR_NAME);
100
try {
101
102
if (!pkgDir.exists() && !pkgDir.mkdirs()) {
103
throw new Error("Failed to create " + pkgDir);
104
}
105
106
107
String javaTemplate = readTemplate(templateFile);
108
File java0 = new File(pkgDir, "Class0.java");
109
File class0 = new File(pkgDir, "Class0.class");
110
writeSource(java0, generateSource(javaTemplate, 0));
111
112
/*
113
* Generating and compiling all the sources is not our way -
114
* too easy and too slow.
115
* We compile just first class and use ASM to obtain others
116
* via instrumenting.
117
*/
118
File[] toCompile = {java0};
119
compile(toCompile, tmpArea.getAbsolutePath());
120
byte[] classTemplate = readFile(class0); // the first compiled class
121
createJar(new File(destDir, JAR_NAME), javaTemplate, classTemplate, count);
122
123
124
deleteFolder(tmpArea);
125
long endTime = System.currentTimeMillis();
126
System.out.println("Success in " + ((endTime - startTime)/1000) + " seconds");
127
} catch (Throwable whatever) {
128
throw new Error(whatever);
129
}
130
}
131
132
/**
133
* Generates source number num.
134
* @param template template to generate from
135
* @param num number
136
* @return content of java file
137
*/
138
String generateSource(String template, int num) {
139
return template.replaceAll("_NNN_", "" + num);
140
}
141
142
/**
143
* Reads content of the given file.
144
* @param file name of file to read
145
* @return file content
146
* @throws IOException if something bad has happened
147
*/
148
String readTemplate(String file) throws IOException {
149
if (!new File(file).exists()) {
150
throw new Error("Template " + file + " doesn't exist");
151
}
152
List<String> lines = Files.readAllLines(Paths.get(file));
153
StringBuilder sb = new StringBuilder();
154
for (String line: lines) {
155
if (line.trim().startsWith("#")) {
156
continue;
157
}
158
sb.append(line).append(System.lineSeparator());
159
}
160
return sb.toString();
161
}
162
163
/**
164
* Writes given content to the given file.
165
*
166
* @param file to create
167
* @param content java source
168
* @throws IOException if something bad has happened
169
*/
170
void writeSource(File file, String content) throws IOException {
171
List<String> list = Arrays.asList(content.split(System.lineSeparator()));
172
Files.write(Paths.get(file.getAbsolutePath()), list);
173
}
174
175
176
/**
177
* Compiles given files into given folder.
178
*
179
* @param files to compile
180
* @param destDir where to compile
181
* @throws IOException
182
*/
183
void compile(File[] files, String destDir) throws IOException {
184
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
185
List<String> optionList = new ArrayList<>();
186
optionList.addAll(Arrays.asList("-d", destDir));
187
StandardJavaFileManager sjfm = compiler.getStandardFileManager(null, null, null);
188
Iterable<? extends JavaFileObject> fileObjects = sjfm.getJavaFileObjects(files);
189
JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, optionList, null, fileObjects);
190
task.call();
191
sjfm.close();
192
}
193
194
/**
195
* Puts a number of classes and java sources in the given jar.
196
*
197
* @param jarFile name of jar file
198
* @param javaTemplate content of java source template
199
* @param classTemplate content of compiled java class
200
* @param count number of classes to generate
201
* @throws IOException
202
*/
203
void createJar(File jarFile, String javaTemplate, byte[] classTemplate, int count) throws IOException {
204
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(jarFile), new Manifest())) {
205
for (int i = 1; i <= count; i++) {
206
String name = PKG_DIR_NAME + "/Class" + i;
207
jar.putNextEntry(new JarEntry(name + ".java"));
208
byte[] content = generateSource(javaTemplate, 0).getBytes();
209
jar.write(content, 0, content.length);
210
211
jar.putNextEntry(new JarEntry(name + ".class"));
212
content = morphClass(classTemplate, name);
213
jar.write(content, 0, content.length);
214
}
215
}
216
}
217
218
byte[] readFile(File f) throws IOException {
219
return Files.readAllBytes(Paths.get(f.getAbsolutePath()));
220
}
221
222
void writeFile(File f, byte[] content) throws IOException {
223
Files.write(Paths.get(f.getAbsolutePath()), content);
224
}
225
226
void deleteFolder(File dir) throws IOException {
227
Files.walkFileTree(Paths.get(dir.getAbsolutePath()), new FileVisitor<Path>() {
228
229
@Override
230
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
231
return FileVisitResult.CONTINUE;
232
}
233
234
@Override
235
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
236
Files.delete(file);
237
return FileVisitResult.CONTINUE;
238
}
239
240
@Override
241
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
242
return FileVisitResult.CONTINUE;
243
}
244
245
@Override
246
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
247
Files.delete(dir);
248
return FileVisitResult.CONTINUE;
249
}
250
251
});
252
}
253
254
/**
255
* Puts new name on the given class.
256
*
257
* @param classToMorph class file content
258
* @param newName new name
259
* @return new class file to write into class
260
*/
261
byte[] morphClass(byte[] classToMorph, String newName) {
262
ClassReader cr = new ClassReader(classToMorph);
263
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
264
ClassVisitor cv = new ClassRenamer(cw, newName);
265
cr.accept(cv, 0);
266
return cw.toByteArray();
267
}
268
269
/**
270
* Visitor to rename class.
271
*/
272
static class ClassRenamer extends ClassVisitor implements Opcodes {
273
private final String newName;
274
275
public ClassRenamer(ClassVisitor cv, String newName) {
276
super(ASM4, cv);
277
this.newName = newName;
278
}
279
280
@Override
281
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
282
cv.visit(version, access, newName, signature, superName, interfaces);
283
}
284
285
}
286
}
287
288