Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/io/FileDescriptor/Sharing.java
41149 views
1
/*
2
* Copyright (c) 2011, 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 7105952 6322678 7082769
27
* @summary Improve finalisation for FileInputStream/FileOutputStream/RandomAccessFile
28
* @run main/othervm Sharing
29
*/
30
31
import java.io.*;
32
import java.nio.channels.FileChannel;
33
import java.nio.channels.FileLock;
34
import java.util.concurrent.CountDownLatch;
35
36
public class Sharing {
37
38
static final int numFiles = 10;
39
static volatile boolean fail;
40
41
public static void main(String[] args) throws Exception {
42
TestFinalizer();
43
TestMultipleFD();
44
TestIsValid();
45
MultiThreadedFD();
46
TestCloseAll();
47
}
48
49
/**
50
* Finalizer shouldn't discard a file descriptor until all streams have
51
* finished with it.
52
*/
53
private static void TestFinalizer() throws Exception {
54
FileDescriptor fd = null;
55
File tempFile = new File("TestFinalizer1.txt");
56
tempFile.deleteOnExit();
57
try (Writer writer = new FileWriter(tempFile)) {
58
for (int i=0; i<5; i++) {
59
writer.write("test file content test file content");
60
}
61
}
62
63
FileInputStream fis1 = new FileInputStream(tempFile);
64
fd = fis1.getFD();
65
// Create a new FIS based on the existing FD (so the two FIS's share the same native fd)
66
try (FileInputStream fis2 = new FileInputStream(fd)) {
67
// allow fis1 to be gc'ed
68
fis1 = null;
69
int ret = 0;
70
while(ret >= 0) {
71
// encourage gc
72
System.gc();
73
// read from fis2 - when fis1 is gc'ed and finalizer is run, read will fail
74
System.out.print(".");
75
ret = fis2.read();
76
}
77
}
78
79
// variation of above. Use RandomAccessFile to obtain a filedescriptor
80
File testFinalizerFile = new File("TestFinalizer");
81
RandomAccessFile raf = new RandomAccessFile(testFinalizerFile, "rw");
82
raf.writeBytes("test file content test file content");
83
raf.seek(0L);
84
fd = raf.getFD();
85
try (FileInputStream fis3 = new FileInputStream(fd)) {
86
// allow raf to be gc'ed
87
raf = null;
88
int ret = 0;
89
while (ret >= 0) {
90
// encourage gc
91
System.gc();
92
/*
93
* read from fis3 - when raf is gc'ed and finalizer is run,
94
* fd should still be valid.
95
*/
96
System.out.print(".");
97
ret = fis3.read();
98
}
99
} finally {
100
testFinalizerFile.delete();
101
}
102
}
103
104
/**
105
* Exercise FileDispatcher close()/preClose()
106
*/
107
private static void TestMultipleFD() throws Exception {
108
RandomAccessFile raf = null;
109
FileOutputStream fos = null;
110
FileInputStream fis = null;
111
FileChannel fc = null;
112
FileLock fileLock = null;
113
114
File test1 = new File("test1");
115
try {
116
raf = new RandomAccessFile(test1, "rw");
117
fos = new FileOutputStream(raf.getFD());
118
fis = new FileInputStream(raf.getFD());
119
fc = raf.getChannel();
120
fileLock = fc.lock();
121
raf.setLength(0L);
122
fos.flush();
123
fos.write("TEST".getBytes());
124
} finally {
125
if (fileLock != null) fileLock.release();
126
if (fis != null) fis.close();
127
if (fos != null) fos.close();
128
if (raf != null) raf.close();
129
test1.delete();
130
}
131
132
/*
133
* Close out in different order to ensure FD is not
134
* closed out too early
135
*/
136
File test2 = new File("test2");
137
try {
138
raf = new RandomAccessFile(test2, "rw");
139
fos = new FileOutputStream(raf.getFD());
140
fis = new FileInputStream(raf.getFD());
141
fc = raf.getChannel();
142
fileLock = fc.lock();
143
raf.setLength(0L);
144
fos.flush();
145
fos.write("TEST".getBytes());
146
} finally {
147
if (fileLock != null) fileLock.release();
148
if (raf != null) raf.close();
149
if (fos != null) fos.close();
150
if (fis != null) fis.close();
151
test2.delete();
152
}
153
154
// one more time, fos first this time
155
File test3 = new File("test3");
156
try {
157
raf = new RandomAccessFile(test3, "rw");
158
fos = new FileOutputStream(raf.getFD());
159
fis = new FileInputStream(raf.getFD());
160
fc = raf.getChannel();
161
fileLock = fc.lock();
162
raf.setLength(0L);
163
fos.flush();
164
fos.write("TEST".getBytes());
165
} finally {
166
if (fileLock != null) fileLock.release();
167
if (fos != null) fos.close();
168
if (raf != null) raf.close();
169
if (fis != null) fis.close();
170
test3.delete();
171
}
172
}
173
174
/**
175
* Similar to TestMultipleFD() but this time we
176
* just get and use FileDescriptor.valid() for testing.
177
*/
178
private static void TestIsValid() throws Exception {
179
FileDescriptor fd = null;
180
RandomAccessFile raf = null;
181
FileOutputStream fos = null;
182
FileInputStream fis = null;
183
FileChannel fc = null;
184
185
File test1 = new File("test1");
186
try {
187
raf = new RandomAccessFile(test1, "rw");
188
fd = raf.getFD();
189
fos = new FileOutputStream(fd);
190
fis = new FileInputStream(fd);
191
} finally {
192
try {
193
if (fis != null) fis.close();
194
if (fd.valid()) {
195
throw new RuntimeException("[FIS close()] FileDescriptor shouldn't be valid");
196
}
197
if (fos != null) fos.close();
198
if (raf != null) raf.close();
199
} finally {
200
test1.delete();
201
}
202
}
203
204
/*
205
* Close out in different order to ensure FD is
206
* closed correctly.
207
*/
208
File test2 = new File("test2");
209
try {
210
raf = new RandomAccessFile(test2, "rw");
211
fd = raf.getFD();
212
fos = new FileOutputStream(fd);
213
fis = new FileInputStream(fd);
214
} finally {
215
try {
216
if (raf != null) raf.close();
217
if (fd.valid()) {
218
throw new RuntimeException("[RAF close()] FileDescriptor shouldn't be valid");
219
}
220
if (fos != null) fos.close();
221
if (fis != null) fis.close();
222
} finally {
223
test2.delete();
224
}
225
}
226
227
// one more time, fos first this time
228
File test3 = new File("test3");
229
try {
230
raf = new RandomAccessFile(test3, "rw");
231
fd = raf.getFD();
232
fos = new FileOutputStream(fd);
233
fis = new FileInputStream(fd);
234
} finally {
235
try {
236
if (fos != null) fos.close();
237
if (fd.valid()) {
238
throw new RuntimeException("[FOS close()] FileDescriptor shouldn't be valid");
239
}
240
if (raf != null) raf.close();
241
if (fis != null) fis.close();
242
} finally {
243
test3.delete();
244
}
245
}
246
}
247
248
/**
249
* Test concurrent access to the same FileDescriptor
250
*/
251
private static void MultiThreadedFD() throws Exception {
252
RandomAccessFile raf = null;
253
FileDescriptor fd = null;
254
int numThreads = 2;
255
CountDownLatch done = new CountDownLatch(numThreads);
256
OpenClose[] fileOpenClose = new OpenClose[numThreads];
257
File MultipleThreadedFD = new File("MultipleThreadedFD");
258
try {
259
raf = new RandomAccessFile(MultipleThreadedFD, "rw");
260
fd = raf.getFD();
261
for(int count=0;count<numThreads;count++) {
262
fileOpenClose[count] = new OpenClose(fd, done);
263
fileOpenClose[count].start();
264
}
265
done.await();
266
} finally {
267
try {
268
if(raf != null) raf.close();
269
// fd should now no longer be valid
270
if(fd.valid()) {
271
throw new RuntimeException("FileDescriptor should not be valid");
272
}
273
// OpenClose thread tests failed
274
if(fail) {
275
throw new RuntimeException("OpenClose thread tests failed.");
276
}
277
} finally {
278
MultipleThreadedFD.delete();
279
}
280
}
281
}
282
283
/**
284
* Test closeAll handling in FileDescriptor
285
*/
286
private static void TestCloseAll() throws Exception {
287
File testFile = new File("test");
288
testFile.deleteOnExit();
289
RandomAccessFile raf = new RandomAccessFile(testFile, "rw");
290
FileInputStream fis = new FileInputStream(raf.getFD());
291
fis.close();
292
if (raf.getFD().valid()) {
293
throw new RuntimeException("FD should not be valid.");
294
}
295
296
// Test the suppressed exception handling - FileInputStream
297
298
raf = new RandomAccessFile(testFile, "rw");
299
fis = new FileInputStream(raf.getFD());
300
BadFileInputStream bfis1 = new BadFileInputStream(raf.getFD());
301
BadFileInputStream bfis2 = new BadFileInputStream(raf.getFD());
302
BadFileInputStream bfis3 = new BadFileInputStream(raf.getFD());
303
// extra test - set bfis3 to null
304
bfis3 = null;
305
try {
306
fis.close();
307
} catch (IOException ioe) {
308
ioe.printStackTrace();
309
if (ioe.getSuppressed().length != 2) {
310
throw new RuntimeException("[FIS]Incorrect number of suppressed " +
311
"exceptions received : " + ioe.getSuppressed().length);
312
}
313
}
314
if (raf.getFD().valid()) {
315
// we should still have closed the FD
316
// even with the exception.
317
throw new RuntimeException("[FIS]TestCloseAll : FD still valid.");
318
}
319
320
// Now test with FileOutputStream
321
322
raf = new RandomAccessFile(testFile, "rw");
323
FileOutputStream fos = new FileOutputStream(raf.getFD());
324
BadFileOutputStream bfos1 = new BadFileOutputStream(raf.getFD());
325
BadFileOutputStream bfos2 = new BadFileOutputStream(raf.getFD());
326
BadFileOutputStream bfos3 = new BadFileOutputStream(raf.getFD());
327
// extra test - set bfos3 to null
328
bfos3 = null;
329
try {
330
fos.close();
331
} catch (IOException ioe) {
332
ioe.printStackTrace();
333
if (ioe.getSuppressed().length != 2) {
334
throw new RuntimeException("[FOS]Incorrect number of suppressed " +
335
"exceptions received : " + ioe.getSuppressed().length);
336
}
337
}
338
if (raf.getFD().valid()) {
339
// we should still have closed the FD
340
// even with the exception.
341
throw new RuntimeException("[FOS]TestCloseAll : FD still valid.");
342
}
343
}
344
345
/**
346
* A thread which will open and close a number of FileInputStreams and
347
* FileOutputStreams referencing the same native file descriptor.
348
*/
349
private static class OpenClose extends Thread {
350
private FileDescriptor fd = null;
351
private CountDownLatch done;
352
FileInputStream[] fisArray = new FileInputStream[numFiles];
353
FileOutputStream[] fosArray = new FileOutputStream[numFiles];
354
355
OpenClose(FileDescriptor filedescriptor, CountDownLatch done) {
356
this.fd = filedescriptor;
357
this.done = done;
358
}
359
360
public void run() {
361
try {
362
for(int i=0;i<numFiles;i++) {
363
fisArray[i] = new FileInputStream(fd);
364
fosArray[i] = new FileOutputStream(fd);
365
}
366
367
// Now close out
368
for(int i=0;i<numFiles;i++) {
369
if(fisArray[i] != null) fisArray[i].close();
370
if(fosArray[i] != null) fosArray[i].close();
371
}
372
373
} catch(IOException ioe) {
374
System.out.println("OpenClose encountered IO issue :" + ioe);
375
fail = true;
376
} finally {
377
if (fd.valid()) { // fd should not be valid after first close() call
378
System.out.println("OpenClose: FileDescriptor shouldn't be valid");
379
fail = true;
380
}
381
done.countDown();
382
}
383
}
384
}
385
386
private static class BadFileInputStream extends FileInputStream {
387
388
BadFileInputStream(FileDescriptor fd) {
389
super(fd);
390
}
391
392
public void close() throws IOException {
393
throw new IOException("Bad close operation");
394
}
395
}
396
397
private static class BadFileOutputStream extends FileOutputStream {
398
399
BadFileOutputStream(FileDescriptor fd) {
400
super(fd);
401
}
402
403
public void close() throws IOException {
404
throw new IOException("Bad close operation");
405
}
406
}
407
408
}
409
410