46 * @see java.io.File
47 * @see java.io.FileDescriptor
48 * @see java.io.FileInputStream
49 * @see java.nio.file.Files#newOutputStream
50 * @since JDK1.0
51 */
52 public
53 class FileOutputStream extends OutputStream
54 {
55 /**
56 * The system dependent file descriptor.
57 */
58 private final FileDescriptor fd;
59
60 /**
61 * True if the file is opened for append.
62 */
63 private final boolean append;
64
65 /**
66 * The associated channel, initalized lazily.
67 */
68 private FileChannel channel;
69
70 private final Object closeLock = new Object();
71 private volatile boolean closed = false;
72 private static final ThreadLocal<Boolean> runningFinalize =
73 new ThreadLocal<>();
74
75 private static boolean isRunningFinalize() {
76 Boolean val;
77 if ((val = runningFinalize.get()) != null)
78 return val.booleanValue();
79 return false;
80 }
81
82 /**
83 * Creates a file output stream to write to the file with the
84 * specified name. A new <code>FileDescriptor</code> object is
85 * created to represent this file connection.
86 * <p>
87 * First, if there is a security manager, its <code>checkWrite</code>
88 * method is called with <code>name</code> as its argument.
89 * <p>
90 * If the file exists but is a directory rather than a regular file, does
91 * not exist but cannot be created, or cannot be opened for any other
92 * reason then a <code>FileNotFoundException</code> is thrown.
93 *
94 * @param name the system-dependent filename
95 * @exception FileNotFoundException if the file exists but is a directory
96 * rather than a regular file, does not exist but cannot
97 * be created, or cannot be opened for any other reason
98 * @exception SecurityException if a security manager exists and its
99 * <code>checkWrite</code> method denies write access
100 * to the file.
101 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
338 }
339 closed = true;
340 }
341
342 if (channel != null) {
343 /*
344 * Decrement FD use count associated with the channel
345 * The use count is incremented whenever a new channel
346 * is obtained from this stream.
347 */
348 fd.decrementAndGetUseCount();
349 channel.close();
350 }
351
352 /*
353 * Decrement FD use count associated with this stream
354 */
355 int useCount = fd.decrementAndGetUseCount();
356
357 /*
358 * If FileDescriptor is still in use by another stream, the finalizer
359 * will not close it.
360 */
361 if ((useCount <= 0) || !isRunningFinalize()) {
362 close0();
363 }
364 }
365
366 /**
367 * Returns the file descriptor associated with this stream.
368 *
369 * @return the <code>FileDescriptor</code> object that represents
370 * the connection to the file in the file system being used
371 * by this <code>FileOutputStream</code> object.
372 *
373 * @exception IOException if an I/O error occurs.
374 * @see java.io.FileDescriptor
375 */
376 public final FileDescriptor getFD() throws IOException {
377 if (fd != null) return fd;
378 throw new IOException();
379 }
380
381 /**
407 */
408 fd.incrementAndGetUseCount();
409 }
410 return channel;
411 }
412 }
413
414 /**
415 * Cleans up the connection to the file, and ensures that the
416 * <code>close</code> method of this file output stream is
417 * called when there are no more references to this stream.
418 *
419 * @exception IOException if an I/O error occurs.
420 * @see java.io.FileInputStream#close()
421 */
422 protected void finalize() throws IOException {
423 if (fd != null) {
424 if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
425 flush();
426 } else {
427
428 /*
429 * Finalizer should not release the FileDescriptor if another
430 * stream is still using it. If the user directly invokes
431 * close() then the FileDescriptor is also released.
432 */
433 runningFinalize.set(Boolean.TRUE);
434 try {
435 close();
436 } finally {
437 runningFinalize.set(Boolean.FALSE);
438 }
439 }
440 }
441 }
442
443 private native void close0() throws IOException;
444
445 private static native void initIDs();
446
447 static {
448 initIDs();
449 }
450
451 }
|
46 * @see java.io.File
47 * @see java.io.FileDescriptor
48 * @see java.io.FileInputStream
49 * @see java.nio.file.Files#newOutputStream
50 * @since JDK1.0
51 */
52 public
53 class FileOutputStream extends OutputStream
54 {
55 /**
56 * The system dependent file descriptor.
57 */
58 private final FileDescriptor fd;
59
60 /**
61 * True if the file is opened for append.
62 */
63 private final boolean append;
64
65 /**
66 * The associated channel, initialized lazily.
67 */
68 private FileChannel channel;
69
70 private final Object closeLock = new Object();
71 private volatile boolean closed = false;
72
73 /**
74 * Creates a file output stream to write to the file with the
75 * specified name. A new <code>FileDescriptor</code> object is
76 * created to represent this file connection.
77 * <p>
78 * First, if there is a security manager, its <code>checkWrite</code>
79 * method is called with <code>name</code> as its argument.
80 * <p>
81 * If the file exists but is a directory rather than a regular file, does
82 * not exist but cannot be created, or cannot be opened for any other
83 * reason then a <code>FileNotFoundException</code> is thrown.
84 *
85 * @param name the system-dependent filename
86 * @exception FileNotFoundException if the file exists but is a directory
87 * rather than a regular file, does not exist but cannot
88 * be created, or cannot be opened for any other reason
89 * @exception SecurityException if a security manager exists and its
90 * <code>checkWrite</code> method denies write access
91 * to the file.
92 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
329 }
330 closed = true;
331 }
332
333 if (channel != null) {
334 /*
335 * Decrement FD use count associated with the channel
336 * The use count is incremented whenever a new channel
337 * is obtained from this stream.
338 */
339 fd.decrementAndGetUseCount();
340 channel.close();
341 }
342
343 /*
344 * Decrement FD use count associated with this stream
345 */
346 int useCount = fd.decrementAndGetUseCount();
347
348 /*
349 * If FileDescriptor is still in use by another stream, we
350 * will not close it.
351 */
352 if (useCount <= 0) {
353 close0();
354 }
355 }
356
357 /**
358 * Returns the file descriptor associated with this stream.
359 *
360 * @return the <code>FileDescriptor</code> object that represents
361 * the connection to the file in the file system being used
362 * by this <code>FileOutputStream</code> object.
363 *
364 * @exception IOException if an I/O error occurs.
365 * @see java.io.FileDescriptor
366 */
367 public final FileDescriptor getFD() throws IOException {
368 if (fd != null) return fd;
369 throw new IOException();
370 }
371
372 /**
398 */
399 fd.incrementAndGetUseCount();
400 }
401 return channel;
402 }
403 }
404
405 /**
406 * Cleans up the connection to the file, and ensures that the
407 * <code>close</code> method of this file output stream is
408 * called when there are no more references to this stream.
409 *
410 * @exception IOException if an I/O error occurs.
411 * @see java.io.FileInputStream#close()
412 */
413 protected void finalize() throws IOException {
414 if (fd != null) {
415 if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
416 flush();
417 } else {
418 close();
419 }
420 }
421 }
422
423 private native void close0() throws IOException;
424
425 private static native void initIDs();
426
427 static {
428 initIDs();
429 }
430
431 }
|