Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
73d65ed1
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
73d65ed1
编写于
3月 10, 2008
作者:
L
lmalvent
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
62acf0ec
240ad09d
变更
23
展开全部
隐藏空白更改
内联
并排
Showing
23 changed file
with
1884 addition
and
622 deletion
+1884
-622
make/java/java/mapfile-vers
make/java/java/mapfile-vers
+0
-1
src/share/classes/java/io/FileInputStream.java
src/share/classes/java/io/FileInputStream.java
+6
-6
src/share/classes/java/io/FileOutputStream.java
src/share/classes/java/io/FileOutputStream.java
+17
-30
src/share/classes/java/lang/Process.java
src/share/classes/java/lang/Process.java
+50
-21
src/share/classes/java/lang/ProcessBuilder.java
src/share/classes/java/lang/ProcessBuilder.java
+635
-91
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
+4
-0
src/share/classes/sun/nio/ch/FileChannelImpl.java
src/share/classes/sun/nio/ch/FileChannelImpl.java
+14
-35
src/share/native/java/io/io_util.c
src/share/native/java/io/io_util.c
+6
-6
src/solaris/classes/java/io/FileDescriptor.java
src/solaris/classes/java/io/FileDescriptor.java
+9
-1
src/solaris/classes/java/lang/ProcessImpl.java
src/solaris/classes/java/lang/ProcessImpl.java
+58
-1
src/solaris/classes/java/lang/UNIXProcess.java.linux
src/solaris/classes/java/lang/UNIXProcess.java.linux
+105
-79
src/solaris/classes/java/lang/UNIXProcess.java.solaris
src/solaris/classes/java/lang/UNIXProcess.java.solaris
+209
-183
src/solaris/native/java/io/FileOutputStream_md.c
src/solaris/native/java/io/FileOutputStream_md.c
+4
-7
src/solaris/native/java/lang/UNIXProcess_md.c
src/solaris/native/java/lang/UNIXProcess_md.c
+68
-22
src/windows/classes/java/io/FileDescriptor.java
src/windows/classes/java/io/FileDescriptor.java
+19
-14
src/windows/classes/java/lang/ProcessImpl.java
src/windows/classes/java/lang/ProcessImpl.java
+121
-29
src/windows/native/java/io/FileOutputStream_md.c
src/windows/native/java/io/FileOutputStream_md.c
+4
-32
src/windows/native/java/io/io_util_md.c
src/windows/native/java/io/io_util_md.c
+10
-21
src/windows/native/java/io/io_util_md.h
src/windows/native/java/io/io_util_md.h
+0
-1
src/windows/native/java/lang/ProcessImpl_md.c
src/windows/native/java/lang/ProcessImpl_md.c
+70
-34
src/windows/native/java/lang/java_props_md.c
src/windows/native/java/lang/java_props_md.c
+18
-5
test/java/io/FileOutputStream/AtomicAppend.java
test/java/io/FileOutputStream/AtomicAppend.java
+81
-0
test/java/lang/ProcessBuilder/Basic.java
test/java/lang/ProcessBuilder/Basic.java
+376
-3
未找到文件。
make/java/java/mapfile-vers
浏览文件 @
73d65ed1
...
@@ -85,7 +85,6 @@ SUNWprivate_1.1 {
...
@@ -85,7 +85,6 @@ SUNWprivate_1.1 {
Java_java_io_FileOutputStream_close0;
Java_java_io_FileOutputStream_close0;
Java_java_io_FileOutputStream_initIDs;
Java_java_io_FileOutputStream_initIDs;
Java_java_io_FileOutputStream_open;
Java_java_io_FileOutputStream_open;
Java_java_io_FileOutputStream_openAppend;
Java_java_io_FileOutputStream_write;
Java_java_io_FileOutputStream_write;
Java_java_io_FileOutputStream_writeBytes;
Java_java_io_FileOutputStream_writeBytes;
Java_java_io_FileSystem_getFileSystem;
Java_java_io_FileSystem_getFileSystem;
...
...
src/share/classes/java/io/FileInputStream.java
浏览文件 @
73d65ed1
...
@@ -48,15 +48,15 @@ public
...
@@ -48,15 +48,15 @@ public
class
FileInputStream
extends
InputStream
class
FileInputStream
extends
InputStream
{
{
/* File Descriptor - handle to the open file */
/* File Descriptor - handle to the open file */
private
FileDescriptor
fd
;
private
final
FileDescriptor
fd
;
private
FileChannel
channel
=
null
;
private
FileChannel
channel
=
null
;
private
Object
closeLock
=
new
Object
();
private
final
Object
closeLock
=
new
Object
();
private
volatile
boolean
closed
=
false
;
private
volatile
boolean
closed
=
false
;
private
static
ThreadLocal
<
Boolean
>
runningFinalize
=
private
static
final
ThreadLocal
<
Boolean
>
runningFinalize
=
new
ThreadLocal
<
Boolean
>();
new
ThreadLocal
<
Boolean
>();
private
static
boolean
isRunningFinalize
()
{
private
static
boolean
isRunningFinalize
()
{
Boolean
val
;
Boolean
val
;
...
@@ -151,7 +151,7 @@ class FileInputStream extends InputStream
...
@@ -151,7 +151,7 @@ class FileInputStream extends InputStream
* is thrown.
* is thrown.
* <p>
* <p>
* This constructor does not throw an exception if <code>fdObj</code>
* This constructor does not throw an exception if <code>fdObj</code>
* is {link java.io.FileDescriptor#valid() invalid}.
* is {
@
link java.io.FileDescriptor#valid() invalid}.
* However, if the methods are invoked on the resulting stream to attempt
* However, if the methods are invoked on the resulting stream to attempt
* I/O on the stream, an <code>IOException</code> is thrown.
* I/O on the stream, an <code>IOException</code> is thrown.
*
*
...
@@ -389,7 +389,7 @@ class FileInputStream extends InputStream
...
@@ -389,7 +389,7 @@ class FileInputStream extends InputStream
* @see java.io.FileInputStream#close()
* @see java.io.FileInputStream#close()
*/
*/
protected
void
finalize
()
throws
IOException
{
protected
void
finalize
()
throws
IOException
{
if
((
fd
!=
null
)
&&
(
fd
!=
fd
.
in
))
{
if
((
fd
!=
null
)
&&
(
fd
!=
FileDescriptor
.
in
))
{
/*
/*
* Finalizer should not release the FileDescriptor if another
* Finalizer should not release the FileDescriptor if another
...
...
src/share/classes/java/io/FileOutputStream.java
浏览文件 @
73d65ed1
...
@@ -52,20 +52,16 @@ public
...
@@ -52,20 +52,16 @@ public
class
FileOutputStream
extends
OutputStream
class
FileOutputStream
extends
OutputStream
{
{
/**
/**
* The system dependent file descriptor. The value is
* The system dependent file descriptor.
* 1 more than actual file descriptor. This means that
* the default value 0 indicates that the file is not open.
*/
*/
private
FileDescriptor
fd
;
private
final
FileDescriptor
fd
;
private
FileChannel
channel
=
null
;
private
FileChannel
channel
=
null
;
private
boolean
append
=
false
;
private
final
Object
closeLock
=
new
Object
();
private
Object
closeLock
=
new
Object
();
private
volatile
boolean
closed
=
false
;
private
volatile
boolean
closed
=
false
;
private
static
ThreadLocal
<
Boolean
>
runningFinalize
=
private
static
final
ThreadLocal
<
Boolean
>
runningFinalize
=
new
ThreadLocal
<
Boolean
>();
new
ThreadLocal
<
Boolean
>();
private
static
boolean
isRunningFinalize
()
{
private
static
boolean
isRunningFinalize
()
{
Boolean
val
;
Boolean
val
;
...
@@ -75,7 +71,7 @@ class FileOutputStream extends OutputStream
...
@@ -75,7 +71,7 @@ class FileOutputStream extends OutputStream
}
}
/**
/**
* Creates a
n output file
stream to write to the file with the
* Creates a
file output
stream to write to the file with the
* specified name. A new <code>FileDescriptor</code> object is
* specified name. A new <code>FileDescriptor</code> object is
* created to represent this file connection.
* created to represent this file connection.
* <p>
* <p>
...
@@ -100,8 +96,8 @@ class FileOutputStream extends OutputStream
...
@@ -100,8 +96,8 @@ class FileOutputStream extends OutputStream
}
}
/**
/**
* Creates a
n output file
stream to write to the file with the specified
* Creates a
file output
stream to write to the file with the specified
*
<code>name</code>
. If the second argument is <code>true</code>, then
*
name
. If the second argument is <code>true</code>, then
* bytes will be written to the end of the file rather than the beginning.
* bytes will be written to the end of the file rather than the beginning.
* A new <code>FileDescriptor</code> object is created to represent this
* A new <code>FileDescriptor</code> object is created to represent this
* file connection.
* file connection.
...
@@ -202,16 +198,11 @@ class FileOutputStream extends OutputStream
...
@@ -202,16 +198,11 @@ class FileOutputStream extends OutputStream
}
}
fd
=
new
FileDescriptor
();
fd
=
new
FileDescriptor
();
fd
.
incrementAndGetUseCount
();
fd
.
incrementAndGetUseCount
();
this
.
append
=
append
;
open
(
name
,
append
);
if
(
append
)
{
openAppend
(
name
);
}
else
{
open
(
name
);
}
}
}
/**
/**
* Creates a
n output file
stream to write to the specified file
* Creates a
file output
stream to write to the specified file
* descriptor, which represents an existing connection to an actual
* descriptor, which represents an existing connection to an actual
* file in the file system.
* file in the file system.
* <p>
* <p>
...
@@ -223,7 +214,7 @@ class FileOutputStream extends OutputStream
...
@@ -223,7 +214,7 @@ class FileOutputStream extends OutputStream
* is thrown.
* is thrown.
* <p>
* <p>
* This constructor does not throw an exception if <code>fdObj</code>
* This constructor does not throw an exception if <code>fdObj</code>
* is {link java.io.FileDescriptor#valid() invalid}.
* is {
@
link java.io.FileDescriptor#valid() invalid}.
* However, if the methods are invoked on the resulting stream to attempt
* However, if the methods are invoked on the resulting stream to attempt
* I/O on the stream, an <code>IOException</code> is thrown.
* I/O on the stream, an <code>IOException</code> is thrown.
*
*
...
@@ -252,16 +243,12 @@ class FileOutputStream extends OutputStream
...
@@ -252,16 +243,12 @@ class FileOutputStream extends OutputStream
}
}
/**
/**
* Opens a file, with the specified name, for writing.
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
*/
private
native
void
open
(
String
name
)
throws
FileNotFoundException
;
/**
* Opens a file, with the specified name, for appending.
* @param name name of file to be opened
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
*/
*/
private
native
void
openAppend
(
String
name
)
throws
FileNotFoundException
;
private
native
void
open
(
String
name
,
boolean
append
)
throws
FileNotFoundException
;
/**
/**
* Writes the specified byte to this file output stream. Implements
* Writes the specified byte to this file output stream. Implements
...
@@ -385,7 +372,7 @@ class FileOutputStream extends OutputStream
...
@@ -385,7 +372,7 @@ class FileOutputStream extends OutputStream
public
FileChannel
getChannel
()
{
public
FileChannel
getChannel
()
{
synchronized
(
this
)
{
synchronized
(
this
)
{
if
(
channel
==
null
)
{
if
(
channel
==
null
)
{
channel
=
FileChannelImpl
.
open
(
fd
,
false
,
true
,
this
,
append
);
channel
=
FileChannelImpl
.
open
(
fd
,
false
,
true
,
this
);
/*
/*
* Increment fd's use count. Invoking the channel's close()
* Increment fd's use count. Invoking the channel's close()
...
@@ -408,7 +395,7 @@ class FileOutputStream extends OutputStream
...
@@ -408,7 +395,7 @@ class FileOutputStream extends OutputStream
*/
*/
protected
void
finalize
()
throws
IOException
{
protected
void
finalize
()
throws
IOException
{
if
(
fd
!=
null
)
{
if
(
fd
!=
null
)
{
if
(
fd
==
fd
.
out
||
fd
==
fd
.
err
)
{
if
(
fd
==
FileDescriptor
.
out
||
fd
==
FileDescriptor
.
err
)
{
flush
();
flush
();
}
else
{
}
else
{
...
...
src/share/classes/java/lang/Process.java
浏览文件 @
73d65ed1
...
@@ -41,18 +41,24 @@ import java.io.*;
...
@@ -41,18 +41,24 @@ import java.io.*;
* <p>The methods that create processes may not work well for special
* <p>The methods that create processes may not work well for special
* processes on certain native platforms, such as native windowing
* processes on certain native platforms, such as native windowing
* processes, daemon processes, Win16/DOS processes on Microsoft
* processes, daemon processes, Win16/DOS processes on Microsoft
* Windows, or shell scripts. The created subprocess does not have
* Windows, or shell scripts.
* its own terminal or console. All its standard I/O (i.e. stdin,
*
* stdout, stderr) operations will be redirected to the parent process
* <p>By default, the created subprocess does not have its own terminal
* through three streams
* or console. All its standard I/O (i.e. stdin, stdout, stderr)
* ({@link #getOutputStream()},
* operations will be redirected to the parent process, where they can
* {@link #getInputStream()},
* be accessed via the streams obtained using the methods
* {@link #getErrorStream()}).
* {@link #getOutputStream()},
* {@link #getInputStream()}, and
* {@link #getErrorStream()}.
* The parent process uses these streams to feed input to and get output
* The parent process uses these streams to feed input to and get output
* from the subprocess. Because some native platforms only provide
* from the subprocess. Because some native platforms only provide
* limited buffer size for standard input and output streams, failure
* limited buffer size for standard input and output streams, failure
* to promptly write the input stream or read the output stream of
* to promptly write the input stream or read the output stream of
* the subprocess may cause the subprocess to block, and even deadlock.
* the subprocess may cause the subprocess to block, or even deadlock.
*
* <p>Where desired, <a href="ProcessBuilder.html#redirect-input">
* subprocess I/O can also be redirected</a>
* using methods of the {@link ProcessBuilder} class.
*
*
* <p>The subprocess is not killed when there are no more references to
* <p>The subprocess is not killed when there are no more references to
* the {@code Process} object, but rather the subprocess
* the {@code Process} object, but rather the subprocess
...
@@ -62,16 +68,22 @@ import java.io.*;
...
@@ -62,16 +68,22 @@ import java.io.*;
* Process} object execute asynchronously or concurrently with respect
* Process} object execute asynchronously or concurrently with respect
* to the Java process that owns the {@code Process} object.
* to the Java process that owns the {@code Process} object.
*
*
* @author unascribed
* <p>As of 1.5, {@link ProcessBuilder#start()} is the preferred way
* @see ProcessBuilder
* to create a {@code Process}.
*
* @since JDK1.0
* @since JDK1.0
*/
*/
public
abstract
class
Process
{
public
abstract
class
Process
{
/**
/**
* Returns the output stream connected to the normal input of the
* Returns the output stream connected to the normal input of the
* subprocess. Output to the stream is piped into the standard
* subprocess. Output to the stream is piped into the standard
* input stream of the process represented by this {@code Process}
* input of the process represented by this {@code Process} object.
* object.
*
* <p>If the standard input of the subprocess has been redirected using
* {@link ProcessBuilder#redirectInput(Redirect)
* ProcessBuilder.redirectInput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
*
*
* <p>Implementation note: It is a good idea for the returned
* <p>Implementation note: It is a good idea for the returned
* output stream to be buffered.
* output stream to be buffered.
...
@@ -84,30 +96,47 @@ public abstract class Process {
...
@@ -84,30 +96,47 @@ public abstract class Process {
/**
/**
* Returns the input stream connected to the normal output of the
* Returns the input stream connected to the normal output of the
* subprocess. The stream obtains data piped from the standard
* subprocess. The stream obtains data piped from the standard
* output stream of the process represented by this {@code
* output of the process represented by this {@code Process} object.
* Process} object.
*
* <p>If the standard output of the subprocess has been redirected using
* {@link ProcessBuilder#redirectOutput(Redirect)
* ProcessBuilder.redirectOutput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>Otherwise, if the standard error of the subprocess has been
* redirected using
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then the input stream returned by this method will receive the
* merged standard output and the standard error of the subprocess.
*
*
* <p>Implementation note: It is a good idea for the returned
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
* input stream to be buffered.
*
*
* @return the input stream connected to the normal output of the
* @return the input stream connected to the normal output of the
* subprocess
* subprocess
* @see ProcessBuilder#redirectErrorStream()
*/
*/
abstract
public
InputStream
getInputStream
();
abstract
public
InputStream
getInputStream
();
/**
/**
* Returns the input stream connected to the error output stream of
* Returns the input stream connected to the error output of the
* the subprocess. The stream obtains data piped from the error
* subprocess. The stream obtains data piped from the error output
* output stream of the process represented by this {@code Process}
* of the process represented by this {@code Process} object.
* object.
*
* <p>If the standard error of the subprocess has been redirected using
* {@link ProcessBuilder#redirectError(Redirect)
* ProcessBuilder.redirectError} or
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
*
* <p>Implementation note: It is a good idea for the returned
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
* input stream to be buffered.
*
*
* @return the input stream connected to the error output
stream
of
* @return the input stream connected to the error output of
* the subprocess
* the subprocess
* @see ProcessBuilder#redirectErrorStream()
*/
*/
abstract
public
InputStream
getErrorStream
();
abstract
public
InputStream
getErrorStream
();
...
...
src/share/classes/java/lang/ProcessBuilder.java
浏览文件 @
73d65ed1
此差异已折叠。
点击以展开。
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
浏览文件 @
73d65ed1
...
@@ -33,4 +33,8 @@ import java.io.FileDescriptor;
...
@@ -33,4 +33,8 @@ import java.io.FileDescriptor;
public
interface
JavaIOFileDescriptorAccess
{
public
interface
JavaIOFileDescriptorAccess
{
public
void
set
(
FileDescriptor
obj
,
int
fd
);
public
void
set
(
FileDescriptor
obj
,
int
fd
);
public
int
get
(
FileDescriptor
fd
);
public
int
get
(
FileDescriptor
fd
);
// Only valid on Windows
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
);
public
long
getHandle
(
FileDescriptor
obj
);
}
}
src/share/classes/sun/nio/ch/FileChannelImpl.java
浏览文件 @
73d65ed1
...
@@ -52,39 +52,37 @@ public class FileChannelImpl
...
@@ -52,39 +52,37 @@ public class FileChannelImpl
{
{
// Used to make native read and write calls
// Used to make native read and write calls
private
static
NativeDispatcher
nd
;
private
static
final
NativeDispatcher
nd
;
// Memory allocation size for mapping buffers
// Memory allocation size for mapping buffers
private
static
long
allocationGranularity
;
private
static
final
long
allocationGranularity
;
// Cached field for MappedByteBuffer.isAMappedBuffer
// Cached field for MappedByteBuffer.isAMappedBuffer
private
static
Field
isAMappedBufferField
;
private
static
final
Field
isAMappedBufferField
;
// File descriptor
// File descriptor
private
FileDescriptor
fd
;
private
final
FileDescriptor
fd
;
// File access mode (immutable)
// File access mode (immutable)
private
boolean
writable
;
private
final
boolean
writable
;
private
boolean
readable
;
private
final
boolean
readable
;
private
boolean
appending
;
// Required to prevent finalization of creating stream (immutable)
// Required to prevent finalization of creating stream (immutable)
private
Object
parent
;
private
final
Object
parent
;
// Thread-safe set of IDs of native threads, for signalling
// Thread-safe set of IDs of native threads, for signalling
private
NativeThreadSet
threads
=
new
NativeThreadSet
(
2
);
private
final
NativeThreadSet
threads
=
new
NativeThreadSet
(
2
);
// Lock for operations involving position and size
// Lock for operations involving position and size
private
Object
positionLock
=
new
Object
();
private
final
Object
positionLock
=
new
Object
();
private
FileChannelImpl
(
FileDescriptor
fd
,
boolean
readable
,
private
FileChannelImpl
(
FileDescriptor
fd
,
boolean
readable
,
boolean
writable
,
Object
parent
,
boolean
append
)
boolean
writable
,
Object
parent
)
{
{
this
.
fd
=
fd
;
this
.
fd
=
fd
;
this
.
readable
=
readable
;
this
.
readable
=
readable
;
this
.
writable
=
writable
;
this
.
writable
=
writable
;
this
.
parent
=
parent
;
this
.
parent
=
parent
;
this
.
appending
=
append
;
}
}
// Invoked by getChannel() methods
// Invoked by getChannel() methods
...
@@ -94,14 +92,7 @@ public class FileChannelImpl
...
@@ -94,14 +92,7 @@ public class FileChannelImpl
boolean
readable
,
boolean
writable
,
boolean
readable
,
boolean
writable
,
Object
parent
)
Object
parent
)
{
{
return
new
FileChannelImpl
(
fd
,
readable
,
writable
,
parent
,
false
);
return
new
FileChannelImpl
(
fd
,
readable
,
writable
,
parent
);
}
public
static
FileChannel
open
(
FileDescriptor
fd
,
boolean
readable
,
boolean
writable
,
Object
parent
,
boolean
append
)
{
return
new
FileChannelImpl
(
fd
,
readable
,
writable
,
parent
,
append
);
}
}
private
void
ensureOpen
()
throws
IOException
{
private
void
ensureOpen
()
throws
IOException
{
...
@@ -134,15 +125,7 @@ public class FileChannelImpl
...
@@ -134,15 +125,7 @@ public class FileChannelImpl
// superclass AbstractInterruptibleChannel, but the isOpen logic in
// superclass AbstractInterruptibleChannel, but the isOpen logic in
// that method will prevent this method from being reinvoked.
// that method will prevent this method from being reinvoked.
//
//
if
(
parent
instanceof
FileInputStream
)
((
java
.
io
.
Closeable
)
parent
).
close
();
((
FileInputStream
)
parent
).
close
();
else
if
(
parent
instanceof
FileOutputStream
)
((
FileOutputStream
)
parent
).
close
();
else
if
(
parent
instanceof
RandomAccessFile
)
((
RandomAccessFile
)
parent
).
close
();
else
assert
false
;
}
else
{
}
else
{
nd
.
close
(
fd
);
nd
.
close
(
fd
);
}
}
...
@@ -218,8 +201,6 @@ public class FileChannelImpl
...
@@ -218,8 +201,6 @@ public class FileChannelImpl
if
(!
isOpen
())
if
(!
isOpen
())
return
0
;
return
0
;
ti
=
threads
.
add
();
ti
=
threads
.
add
();
if
(
appending
)
position
(
size
());
do
{
do
{
n
=
IOUtil
.
write
(
fd
,
src
,
-
1
,
nd
,
positionLock
);
n
=
IOUtil
.
write
(
fd
,
src
,
-
1
,
nd
,
positionLock
);
}
while
((
n
==
IOStatus
.
INTERRUPTED
)
&&
isOpen
());
}
while
((
n
==
IOStatus
.
INTERRUPTED
)
&&
isOpen
());
...
@@ -244,8 +225,6 @@ public class FileChannelImpl
...
@@ -244,8 +225,6 @@ public class FileChannelImpl
if
(!
isOpen
())
if
(!
isOpen
())
return
0
;
return
0
;
ti
=
threads
.
add
();
ti
=
threads
.
add
();
if
(
appending
)
position
(
size
());
do
{
do
{
n
=
IOUtil
.
write
(
fd
,
srcs
,
nd
);
n
=
IOUtil
.
write
(
fd
,
srcs
,
nd
);
}
while
((
n
==
IOStatus
.
INTERRUPTED
)
&&
isOpen
());
}
while
((
n
==
IOStatus
.
INTERRUPTED
)
&&
isOpen
());
...
@@ -1051,7 +1030,7 @@ public class FileChannelImpl
...
@@ -1051,7 +1030,7 @@ public class FileChannelImpl
private
FileKey
fileKey
;
private
FileKey
fileKey
;
FileLockReference
(
FileLock
referent
,
FileLockReference
(
FileLock
referent
,
ReferenceQueue
queue
,
ReferenceQueue
<
FileLock
>
queue
,
FileKey
key
)
{
FileKey
key
)
{
super
(
referent
,
queue
);
super
(
referent
,
queue
);
this
.
fileKey
=
key
;
this
.
fileKey
=
key
;
...
@@ -1073,7 +1052,7 @@ public class FileChannelImpl
...
@@ -1073,7 +1052,7 @@ public class FileChannelImpl
new
ConcurrentHashMap
<
FileKey
,
ArrayList
<
FileLockReference
>>();
new
ConcurrentHashMap
<
FileKey
,
ArrayList
<
FileLockReference
>>();
// reference queue for cleared refs
// reference queue for cleared refs
private
static
ReferenceQueue
queue
=
new
ReferenceQueue
();
private
static
ReferenceQueue
<
FileLock
>
queue
=
new
ReferenceQueue
<
FileLock
>
();
// the enclosing file channel
// the enclosing file channel
private
FileChannelImpl
fci
;
private
FileChannelImpl
fci
;
...
...
src/share/native/java/io/io_util.c
浏览文件 @
73d65ed1
...
@@ -40,7 +40,7 @@ readSingle(JNIEnv *env, jobject this, jfieldID fid) {
...
@@ -40,7 +40,7 @@ readSingle(JNIEnv *env, jobject this, jfieldID fid) {
char
ret
;
char
ret
;
FD
fd
=
GET_FD
(
this
,
fid
);
FD
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
-
1
;
return
-
1
;
}
}
nread
=
IO_Read
(
fd
,
&
ret
,
1
);
nread
=
IO_Read
(
fd
,
&
ret
,
1
);
...
@@ -94,8 +94,8 @@ readBytes(JNIEnv *env, jobject this, jbyteArray bytes,
...
@@ -94,8 +94,8 @@ readBytes(JNIEnv *env, jobject this, jbyteArray bytes,
fd
=
GET_FD
(
this
,
fid
);
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
-
1
;
return
-
1
;
}
}
nread
=
IO_Read
(
fd
,
buf
,
len
);
nread
=
IO_Read
(
fd
,
buf
,
len
);
...
@@ -121,7 +121,7 @@ writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid) {
...
@@ -121,7 +121,7 @@ writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid) {
int
n
;
int
n
;
FD
fd
=
GET_FD
(
this
,
fid
);
FD
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
return
;
}
}
n
=
IO_Write
(
fd
,
&
c
,
1
);
n
=
IO_Write
(
fd
,
&
c
,
1
);
...
@@ -172,8 +172,8 @@ writeBytes(JNIEnv *env, jobject this, jbyteArray bytes,
...
@@ -172,8 +172,8 @@ writeBytes(JNIEnv *env, jobject this, jbyteArray bytes,
while
(
len
>
0
)
{
while
(
len
>
0
)
{
fd
=
GET_FD
(
this
,
fid
);
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
break
;
}
}
n
=
IO_Write
(
fd
,
buf
+
off
,
len
);
n
=
IO_Write
(
fd
,
buf
+
off
,
len
);
if
(
n
==
JVM_IO_ERR
)
{
if
(
n
==
JVM_IO_ERR
)
{
...
...
src/solaris/classes/java/io/FileDescriptor.java
浏览文件 @
73d65ed1
...
@@ -152,11 +152,19 @@ public final class FileDescriptor {
...
@@ -152,11 +152,19 @@ public final class FileDescriptor {
public
int
get
(
FileDescriptor
obj
)
{
public
int
get
(
FileDescriptor
obj
)
{
return
obj
.
fd
;
return
obj
.
fd
;
}
}
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
)
{
throw
new
UnsupportedOperationException
();
}
public
long
getHandle
(
FileDescriptor
obj
)
{
throw
new
UnsupportedOperationException
();
}
}
}
);
);
}
}
// pac
akge private methods used by FIS,
FOS and RAF
// pac
kage private methods used by FIS,
FOS and RAF
int
incrementAndGetUseCount
()
{
int
incrementAndGetUseCount
()
{
return
useCount
.
incrementAndGet
();
return
useCount
.
incrementAndGet
();
...
...
src/solaris/classes/java/lang/ProcessImpl.java
浏览文件 @
73d65ed1
...
@@ -26,7 +26,10 @@
...
@@ -26,7 +26,10 @@
package
java.lang
;
package
java.lang
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.Process
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.lang.ProcessBuilder.Redirect
;
import
java.lang.ProcessBuilder.Redirect
;
/**
/**
* This class is for the exclusive use of ProcessBuilder.start() to
* This class is for the exclusive use of ProcessBuilder.start() to
...
@@ -36,6 +39,9 @@ import java.lang.Process;
...
@@ -36,6 +39,9 @@ import java.lang.Process;
* @since 1.5
* @since 1.5
*/
*/
final
class
ProcessImpl
{
final
class
ProcessImpl
{
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
();
private
ProcessImpl
()
{}
// Not instantiable
private
ProcessImpl
()
{}
// Not instantiable
private
static
byte
[]
toCString
(
String
s
)
{
private
static
byte
[]
toCString
(
String
s
)
{
...
@@ -54,6 +60,7 @@ final class ProcessImpl {
...
@@ -54,6 +60,7 @@ final class ProcessImpl {
static
Process
start
(
String
[]
cmdarray
,
static
Process
start
(
String
[]
cmdarray
,
java
.
util
.
Map
<
String
,
String
>
environment
,
java
.
util
.
Map
<
String
,
String
>
environment
,
String
dir
,
String
dir
,
ProcessBuilder
.
Redirect
[]
redirects
,
boolean
redirectErrorStream
)
boolean
redirectErrorStream
)
throws
IOException
throws
IOException
{
{
...
@@ -78,11 +85,61 @@ final class ProcessImpl {
...
@@ -78,11 +85,61 @@ final class ProcessImpl {
int
[]
envc
=
new
int
[
1
];
int
[]
envc
=
new
int
[
1
];
byte
[]
envBlock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
,
envc
);
byte
[]
envBlock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
,
envc
);
int
[]
std_fds
;
FileInputStream
f0
=
null
;
FileOutputStream
f1
=
null
;
FileOutputStream
f2
=
null
;
try
{
if
(
redirects
==
null
)
{
std_fds
=
new
int
[]
{
-
1
,
-
1
,
-
1
};
}
else
{
std_fds
=
new
int
[
3
];
if
(
redirects
[
0
]
==
Redirect
.
PIPE
)
std_fds
[
0
]
=
-
1
;
else
if
(
redirects
[
0
]
==
Redirect
.
INHERIT
)
std_fds
[
0
]
=
0
;
else
{
f0
=
new
FileInputStream
(
redirects
[
0
].
file
());
std_fds
[
0
]
=
fdAccess
.
get
(
f0
.
getFD
());
}
if
(
redirects
[
1
]
==
Redirect
.
PIPE
)
std_fds
[
1
]
=
-
1
;
else
if
(
redirects
[
1
]
==
Redirect
.
INHERIT
)
std_fds
[
1
]
=
1
;
else
{
f1
=
redirects
[
1
].
toFileOutputStream
();
std_fds
[
1
]
=
fdAccess
.
get
(
f1
.
getFD
());
}
if
(
redirects
[
2
]
==
Redirect
.
PIPE
)
std_fds
[
2
]
=
-
1
;
else
if
(
redirects
[
2
]
==
Redirect
.
INHERIT
)
std_fds
[
2
]
=
2
;
else
{
f2
=
redirects
[
2
].
toFileOutputStream
();
std_fds
[
2
]
=
fdAccess
.
get
(
f2
.
getFD
());
}
}
return
new
UNIXProcess
return
new
UNIXProcess
(
toCString
(
cmdarray
[
0
]),
(
toCString
(
cmdarray
[
0
]),
argBlock
,
args
.
length
,
argBlock
,
args
.
length
,
envBlock
,
envc
[
0
],
envBlock
,
envc
[
0
],
toCString
(
dir
),
toCString
(
dir
),
std_fds
,
redirectErrorStream
);
redirectErrorStream
);
}
finally
{
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
try
{
if
(
f0
!=
null
)
f0
.
close
();
}
finally
{
try
{
if
(
f1
!=
null
)
f1
.
close
();
}
finally
{
if
(
f2
!=
null
)
f2
.
close
();
}
}
}
}
}
}
}
src/solaris/classes/java/lang/UNIXProcess.java.linux
浏览文件 @
73d65ed1
/*
/*
*
Copyright
1995
-
200
6
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
Copyright
1995
-
200
8
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
*
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
...
@@ -34,9 +34,9 @@ import java.io.*;
...
@@ -34,9 +34,9 @@ import java.io.*;
*/
*/
final
class
UNIXProcess
extends
Process
{
final
class
UNIXProcess
extends
Process
{
private
FileDescriptor
stdin_fd
;
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
private
FileDescriptor
stdout_fd
;
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
()
;
private
FileDescriptor
stderr_fd
;
private
int
pid
;
private
int
pid
;
private
int
exitcode
;
private
int
exitcode
;
private
boolean
hasExited
;
private
boolean
hasExited
;
...
@@ -48,15 +48,26 @@ final class UNIXProcess extends Process {
...
@@ -48,15 +48,26 @@ final class UNIXProcess extends Process {
/*
this
is
for
the
reaping
thread
*/
/*
this
is
for
the
reaping
thread
*/
private
native
int
waitForProcessExit
(
int
pid
);
private
native
int
waitForProcessExit
(
int
pid
);
/**
*
Create
a
process
using
fork
(
2
)
and
exec
(
2
).
*
*
@
param
std_fds
array
of
file
descriptors
.
Indexes
0
,
1
,
and
*
2
correspond
to
standard
input
,
standard
output
and
*
standard
error
,
respectively
.
On
input
,
a
value
of
-
1
*
means
to
create
a
pipe
to
connect
child
and
parent
*
processes
.
On
output
,
a
value
which
is
not
-
1
is
the
*
parent
pipe
fd
corresponding
to
the
pipe
which
has
*
been
created
.
An
element
of
this
array
is
-
1
on
input
*
if
and
only
if
it
is
<
em
>
not
</
em
>
-
1
on
output
.
*
@
return
the
pid
of
the
subprocess
*/
private
native
int
forkAndExec
(
byte
[]
prog
,
private
native
int
forkAndExec
(
byte
[]
prog
,
byte
[]
argBlock
,
int
argc
,
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
byte
[]
dir
,
boolean
redirectErrorStream
,
int
[]
std_fds
,
FileDescriptor
stdin_fd
,
boolean
redirectErrorStream
)
FileDescriptor
stdout_fd
,
throws
IOException
;
FileDescriptor
stderr_fd
)
throws
IOException
;
/*
In
the
process
constructor
we
wait
on
this
gate
until
the
process
*/
/*
In
the
process
constructor
we
wait
on
this
gate
until
the
process
*/
/*
has
been
created
.
Then
we
return
from
the
constructor
.
*/
/*
has
been
created
.
Then
we
return
from
the
constructor
.
*/
...
@@ -97,67 +108,82 @@ final class UNIXProcess extends Process {
...
@@ -97,67 +108,82 @@ final class UNIXProcess extends Process {
}
}
UNIXProcess
(
final
byte
[]
prog
,
UNIXProcess
(
final
byte
[]
prog
,
final
byte
[]
argBlock
,
final
int
argc
,
final
byte
[]
argBlock
,
final
int
argc
,
final
byte
[]
envBlock
,
final
int
envc
,
final
byte
[]
envBlock
,
final
int
envc
,
final
byte
[]
dir
,
final
byte
[]
dir
,
final
boolean
redirectErrorStream
)
final
int
[]
std_fds
,
final
boolean
redirectErrorStream
)
throws
IOException
{
throws
IOException
{
stdin_fd
=
new
FileDescriptor
();
stdout_fd
=
new
FileDescriptor
();
stderr_fd
=
new
FileDescriptor
();
final
Gate
gate
=
new
Gate
();
final
Gate
gate
=
new
Gate
();
/*
/*
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
is
started
.
That
thread
is
the
only
thread
which
waits
*
is
started
.
That
thread
is
the
only
thread
which
waits
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
* locks while doing so. This design allows waitFor() and
* locks while doing so. This design allows waitFor() and
* exitStatus() to be safely executed in parallel (and they
* exitStatus() to be safely executed in parallel (and they
* need no native code).
* need no native code).
*/
*/
java.security.AccessController.doPrivileged(
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction
() {
new java.security.PrivilegedAction<Void>
() {
public Object
run() {
public Void
run() {
Thread t = new Thread("process reaper") {
Thread t = new Thread("process reaper") {
public void run() {
public void run() {
try {
try {
pid = forkAndExec(prog,
pid = forkAndExec(prog,
argBlock, argc,
argBlock, argc,
envBlock, envc,
envBlock, envc,
dir,
dir,
redirectErrorStream
,
std_fds
,
stdin_fd, stdout_fd, stderr_fd
);
redirectErrorStream
);
} catch (IOException e) {
} catch (IOException e) {
gate.setException(e); /*remember to rethrow later*/
gate.setException(e); /*remember to rethrow later*/
gate.exit();
gate.exit();
return;
return;
}
}
java.security.AccessController.doPrivileged(
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
new java.security.PrivilegedAction<Void>() {
public Object run() {
public Void run() {
stdin_stream = new BufferedOutputStream(new
if (std_fds[0] == -1)
FileOutputStream(stdin_fd));
stdin_stream = new ProcessBuilder.NullOutputStream();
stdout_stream = new BufferedInputStream(new
else {
FileInputStream(stdout_fd));
FileDescriptor stdin_fd = new FileDescriptor();
fdAccess.set(stdin_fd, std_fds[0]);
stdin_stream = new BufferedOutputStream(
new FileOutputStream(stdin_fd));
}
if (std_fds[1] == -1)
stdout_stream = new ProcessBuilder.NullInputStream();
else {
FileDescriptor stdout_fd = new FileDescriptor();
fdAccess.set(stdout_fd, std_fds[1]);
stdout_stream = new BufferedInputStream(
new FileInputStream(stdout_fd));
}
if (std_fds[2] == -1)
stderr_stream = new ProcessBuilder.NullInputStream();
else {
FileDescriptor stderr_fd = new FileDescriptor();
fdAccess.set(stderr_fd, std_fds[2]);
stderr_stream = new FileInputStream(stderr_fd);
stderr_stream = new FileInputStream(stderr_fd);
return null;
}
}
});
return null; }});
gate.exit(); /* exit from constructor */
gate.exit(); /* exit from constructor */
int res = waitForProcessExit(pid);
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
synchronized (UNIXProcess.this) {
hasExited = true;
hasExited = true;
exitcode = res;
exitcode = res;
UNIXProcess.this.notifyAll();
UNIXProcess.this.notifyAll();
}
}
}
}
};
};
t.setDaemon(true);
t.setDaemon(true);
t.start();
t.start();
return null;
return null; }});
}
});
gate.waitForExit();
gate.waitForExit();
IOException e = gate.getException();
IOException e = gate.getException();
if (e != null)
if (e != null)
...
@@ -165,43 +191,43 @@ final class UNIXProcess extends Process {
...
@@ -165,43 +191,43 @@ final class UNIXProcess extends Process {
}
}
public OutputStream getOutputStream() {
public OutputStream getOutputStream() {
return stdin_stream;
return stdin_stream;
}
}
public InputStream getInputStream() {
public InputStream getInputStream() {
return stdout_stream;
return stdout_stream;
}
}
public InputStream getErrorStream() {
public InputStream getErrorStream() {
return stderr_stream;
return stderr_stream;
}
}
public synchronized int waitFor() throws InterruptedException {
public synchronized int waitFor() throws InterruptedException {
while (!hasExited) {
while (!hasExited) {
wait();
wait();
}
}
return exitcode;
return exitcode;
}
}
public synchronized int exitValue() {
public synchronized int exitValue() {
if (!hasExited) {
if (!hasExited) {
throw new IllegalThreadStateException("process hasn'
t
exited
");
throw new IllegalThreadStateException("process hasn'
t
exited
");
}
}
return exitcode;
return exitcode;
}
}
private static native void destroyProcess(int pid);
private static native void destroyProcess(int pid);
public void destroy() {
public void destroy() {
// There is a risk that pid will be recycled, causing us to
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
// soon, so this is quite safe.
synchronized (this) {
synchronized (this) {
if (!hasExited)
if (!hasExited)
destroyProcess(pid);
destroyProcess(pid);
}
}
try {
try {
stdin_stream.close();
stdin_stream.close();
stdout_stream.close();
stdout_stream.close();
...
@@ -215,6 +241,6 @@ final class UNIXProcess extends Process {
...
@@ -215,6 +241,6 @@ final class UNIXProcess extends Process {
private static native void initIDs();
private static native void initIDs();
static {
static {
initIDs();
initIDs();
}
}
}
}
src/solaris/classes/java/lang/UNIXProcess.java.solaris
浏览文件 @
73d65ed1
/*
/*
*
Copyright
1995
-
200
6
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
Copyright
1995
-
200
8
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
*
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
...
@@ -33,129 +33,155 @@ import java.io.*;
...
@@ -33,129 +33,155 @@ import java.io.*;
*/
*/
final
class
UNIXProcess
extends
Process
{
final
class
UNIXProcess
extends
Process
{
private
FileDescriptor
stdin_fd
;
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
private
FileDescriptor
stdout_fd
;
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
()
;
private
FileDescriptor
stderr_fd
;
private
int
pid
;
private
final
int
pid
;
private
int
exitcode
;
private
int
exitcode
;
private
boolean
hasExited
;
private
boolean
hasExited
;
private
OutputStream
stdin_stream
;
private
OutputStream
stdin_stream
;
private
Buffered
InputStream
stdout_stream
;
private
InputStream
stdout_stream
;
private
DeferredCloseInputStream
stdout_inner_stream
;
private
DeferredCloseInputStream
stdout_inner_stream
;
private
DeferredClose
InputStream
stderr_stream
;
private
InputStream
stderr_stream
;
/*
this
is
for
the
reaping
thread
*/
/*
this
is
for
the
reaping
thread
*/
private
native
int
waitForProcessExit
(
int
pid
);
private
native
int
waitForProcessExit
(
int
pid
);
/**
*
Create
a
process
using
fork
(
2
)
and
exec
(
2
).
*
*
@
param
std_fds
array
of
file
descriptors
.
Indexes
0
,
1
,
and
*
2
correspond
to
standard
input
,
standard
output
and
*
standard
error
,
respectively
.
On
input
,
a
value
of
-
1
*
means
to
create
a
pipe
to
connect
child
and
parent
*
processes
.
On
output
,
a
value
which
is
not
-
1
is
the
*
parent
pipe
fd
corresponding
to
the
pipe
which
has
*
been
created
.
An
element
of
this
array
is
-
1
on
input
*
if
and
only
if
it
is
<
em
>
not
</
em
>
-
1
on
output
.
*
@
return
the
pid
of
the
subprocess
*/
private
native
int
forkAndExec
(
byte
[]
prog
,
private
native
int
forkAndExec
(
byte
[]
prog
,
byte
[]
argBlock
,
int
argc
,
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
byte
[]
dir
,
boolean
redirectErrorStream
,
int
[]
std_fds
,
FileDescriptor
stdin_fd
,
boolean
redirectErrorStream
)
FileDescriptor
stdout_fd
,
throws
IOException
;
FileDescriptor
stderr_fd
)
throws
IOException
;
UNIXProcess
(
final
byte
[]
prog
,
UNIXProcess
(
final
byte
[]
prog
,
final
byte
[]
argBlock
,
int
argc
,
final
byte
[]
argBlock
,
int
argc
,
final
byte
[]
envBlock
,
int
envc
,
final
byte
[]
envBlock
,
int
envc
,
final
byte
[]
dir
,
final
byte
[]
dir
,
final
boolean
redirectErrorStream
)
final
int
[]
std_fds
,
final
boolean
redirectErrorStream
)
throws
IOException
{
throws
IOException
{
stdin_fd
=
new
FileDescriptor
();
pid
=
forkAndExec
(
prog
,
stdout_fd
=
new
FileDescriptor
();
argBlock
,
argc
,
stderr_fd
=
new
FileDescriptor
();
envBlock
,
envc
,
dir
,
pid
=
forkAndExec
(
prog
,
std_fds
,
argBlock
,
argc
,
redirectErrorStream
);
envBlock
,
envc
,
dir
,
java
.
security
.
AccessController
.
doPrivileged
(
redirectErrorStream
,
new
java
.
security
.
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
stdin_fd
,
stdout_fd
,
stderr_fd
);
if
(
std_fds
[
0
]
==
-
1
)
stdin_stream
=
new
ProcessBuilder
.
NullOutputStream
();
java
.
security
.
AccessController
.
doPrivileged
(
else
{
new
java
.
security
.
PrivilegedAction
()
{
FileDescriptor
stdin_fd
=
new
FileDescriptor
();
public
Object
run
()
{
fdAccess
.
set
(
stdin_fd
,
std_fds
[
0
]);
stdin_stream
stdin_stream
=
new
BufferedOutputStream
(
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
));
new
FileOutputStream
(
stdin_fd
));
stdout_inner_stream
=
new
DeferredCloseInputStream
(
stdout_fd
);
}
stdout_stream
=
new
BufferedInputStream
(
stdout_inner_stream
);
stderr_stream
=
new
DeferredCloseInputStream
(
stderr_fd
);
if
(
std_fds
[
1
]
==
-
1
)
return
null
;
stdout_stream
=
new
ProcessBuilder
.
NullInputStream
();
}
else
{
});
FileDescriptor
stdout_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stdout_fd
,
std_fds
[
1
]);
/*
stdout_inner_stream
=
new
DeferredCloseInputStream
(
stdout_fd
);
*
For
each
subprocess
forked
a
corresponding
reaper
thread
stdout_stream
=
new
BufferedInputStream
(
stdout_inner_stream
);
*
is
started
.
That
thread
is
the
only
thread
which
waits
}
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
* locks while doing so. This design allows waitFor() and
if
(
std_fds
[
2
]
==
-
1
)
* exitStatus() to be safely executed in parallel (and they
stderr_stream
=
new
ProcessBuilder
.
NullInputStream
();
* need no native code).
else
{
*/
FileDescriptor
stderr_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stderr_fd
,
std_fds
[
2
]);
java.security.AccessController.doPrivileged(
stderr_stream
=
new
DeferredCloseInputStream
(
stderr_fd
);
new java.security.PrivilegedAction() {
}
public Object run() {
Thread t = new Thread("process reaper") {
return
null
;
}});
public void run() {
int res = waitForProcessExit(pid);
/*
synchronized (UNIXProcess.this) {
*
For
each
subprocess
forked
a
corresponding
reaper
thread
hasExited = true;
*
is
started
.
That
thread
is
the
only
thread
which
waits
exitcode = res;
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
UNIXProcess.this.notifyAll();
* locks while doing so. This design allows waitFor() and
}
* exitStatus() to be safely executed in parallel (and they
}
* need no native code).
};
*/
t.setDaemon(true);
t.start();
java.security.AccessController.doPrivileged(
return null;
new java.security.PrivilegedAction<Void>() { public Void run() {
}
Thread t = new Thread("process reaper") {
});
public void run() {
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
t.setDaemon(true);
t.start();
return null; }});
}
}
public OutputStream getOutputStream() {
public OutputStream getOutputStream() {
return stdin_stream;
return stdin_stream;
}
}
public InputStream getInputStream() {
public InputStream getInputStream() {
return stdout_stream;
return stdout_stream;
}
}
public InputStream getErrorStream() {
public InputStream getErrorStream() {
return stderr_stream;
return stderr_stream;
}
}
public synchronized int waitFor() throws InterruptedException {
public synchronized int waitFor() throws InterruptedException {
while (!hasExited) {
while (!hasExited) {
wait();
wait();
}
}
return exitcode;
return exitcode;
}
}
public synchronized int exitValue() {
public synchronized int exitValue() {
if (!hasExited) {
if (!hasExited) {
throw new IllegalThreadStateException("process hasn'
t
exited
");
throw new IllegalThreadStateException("process hasn'
t
exited
");
}
}
return exitcode;
return exitcode;
}
}
private static native void destroyProcess(int pid);
private static native void destroyProcess(int pid);
public synchronized void destroy() {
public synchronized void destroy() {
// There is a risk that pid will be recycled, causing us to
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
// soon, so this is quite safe.
if (!hasExited)
if (!hasExited)
destroyProcess(pid);
destroyProcess(pid);
try {
try {
stdin_stream.close();
stdin_stream.close();
stdout_inner_stream.closeDeferred(stdout_stream);
if (stdout_inner_stream != null)
stderr_stream.closeDeferred(stderr_stream);
stdout_inner_stream.closeDeferred(stdout_stream);
if (stderr_stream instanceof DeferredCloseInputStream)
((DeferredCloseInputStream) stderr_stream)
.closeDeferred(stderr_stream);
} catch (IOException e) {
} catch (IOException e) {
// ignore
// ignore
}
}
...
@@ -172,99 +198,99 @@ final class UNIXProcess extends Process {
...
@@ -172,99 +198,99 @@ final class UNIXProcess extends Process {
// (EOF) as they did before.
// (EOF) as they did before.
//
//
private static class DeferredCloseInputStream
private static class DeferredCloseInputStream
extends FileInputStream
extends FileInputStream
{
{
private DeferredCloseInputStream(FileDescriptor fd) {
private DeferredCloseInputStream(FileDescriptor fd) {
super(fd);
super(fd);
}
}
private Object lock = new Object();
// For the following fields
private Object lock = new Object();
// For the following fields
private boolean closePending = false;
private boolean closePending = false;
private int useCount = 0;
private int useCount = 0;
private InputStream streamToClose;
private InputStream streamToClose;
private void raise() {
private void raise() {
synchronized (lock) {
synchronized (lock) {
useCount++;
useCount++;
}
}
}
}
private void lower() throws IOException {
private void lower() throws IOException {
synchronized (lock) {
synchronized (lock) {
useCount--;
useCount--;
if (useCount == 0 && closePending) {
if (useCount == 0 && closePending) {
streamToClose.close();
streamToClose.close();
}
}
}
}
}
}
// stc is the actual stream to be closed; it might be this object, or
// stc is the actual stream to be closed; it might be this object, or
// it might be an upstream object for which this object is downstream.
// it might be an upstream object for which this object is downstream.
//
//
private void closeDeferred(InputStream stc) throws IOException {
private void closeDeferred(InputStream stc) throws IOException {
synchronized (lock) {
synchronized (lock) {
if (useCount == 0) {
if (useCount == 0) {
stc.close();
stc.close();
} else {
} else {
closePending = true;
closePending = true;
streamToClose = stc;
streamToClose = stc;
}
}
}
}
}
}
public void close() throws IOException {
public void close() throws IOException {
synchronized (lock) {
synchronized (lock) {
useCount = 0;
useCount = 0;
closePending = false;
closePending = false;
}
}
super.close();
super.close();
}
}
public int read() throws IOException {
public int read() throws IOException {
raise();
raise();
try {
try {
return super.read();
return super.read();
} finally {
} finally {
lower();
lower();
}
}
}
}
public int read(byte[] b) throws IOException {
public int read(byte[] b) throws IOException {
raise();
raise();
try {
try {
return super.read(b);
return super.read(b);
} finally {
} finally {
lower();
lower();
}
}
}
}
public int read(byte[] b, int off, int len) throws IOException {
public int read(byte[] b, int off, int len) throws IOException {
raise();
raise();
try {
try {
return super.read(b, off, len);
return super.read(b, off, len);
} finally {
} finally {
lower();
lower();
}
}
}
}
public long skip(long n) throws IOException {
public long skip(long n) throws IOException {
raise();
raise();
try {
try {
return super.skip(n);
return super.skip(n);
} finally {
} finally {
lower();
lower();
}
}
}
}
public int available() throws IOException {
public int available() throws IOException {
raise();
raise();
try {
try {
return super.available();
return super.available();
} finally {
} finally {
lower();
lower();
}
}
}
}
}
}
...
@@ -272,6 +298,6 @@ final class UNIXProcess extends Process {
...
@@ -272,6 +298,6 @@ final class UNIXProcess extends Process {
private static native void initIDs();
private static native void initIDs();
static {
static {
initIDs();
initIDs();
}
}
}
}
src/solaris/native/java/io/FileOutputStream_md.c
浏览文件 @
73d65ed1
...
@@ -53,13 +53,10 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fdClass) {
...
@@ -53,13 +53,10 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fdClass) {
*/
*/
JNIEXPORT
void
JNICALL
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
);
jstring
path
,
jboolean
append
)
{
}
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
(
append
?
O_APPEND
:
O_TRUNC
));
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_openAppend
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
}
}
JNIEXPORT
void
JNICALL
JNIEXPORT
void
JNICALL
...
...
src/solaris/native/java/lang/UNIXProcess_md.c
浏览文件 @
73d65ed1
/*
/*
* Copyright 1995-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1995-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -479,6 +479,37 @@ closeSafely(int fd)
...
@@ -479,6 +479,37 @@ closeSafely(int fd)
close
(
fd
);
close
(
fd
);
}
}
/*
* Reads nbyte bytes from file descriptor fd into buf,
* The read operation is retried in case of EINTR or partial reads.
*
* Returns number of bytes read (normally nbyte, but may be less in
* case of EOF). In case of read errors, returns -1 and sets errno.
*/
static
ssize_t
readFully
(
int
fd
,
void
*
buf
,
size_t
nbyte
)
{
ssize_t
remaining
=
nbyte
;
for
(;;)
{
ssize_t
n
=
read
(
fd
,
buf
,
remaining
);
if
(
n
==
0
)
{
return
nbyte
-
remaining
;
}
else
if
(
n
>
0
)
{
remaining
-=
n
;
if
(
remaining
<=
0
)
return
nbyte
;
/* We were interrupted in the middle of reading the bytes.
* Unlikely, but possible. */
buf
=
(
void
*
)
(((
char
*
)
buf
)
+
n
);
}
else
if
(
errno
==
EINTR
)
{
/* Strange signals like SIGJVM1 are possible at any time.
* See http://www.dreamsongs.com/WorseIsBetter.html */
}
else
{
return
-
1
;
}
}
}
#ifndef __solaris__
#ifndef __solaris__
#undef fork1
#undef fork1
#define fork1() fork()
#define fork1() fork()
...
@@ -491,10 +522,8 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -491,10 +522,8 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
jbyteArray
argBlock
,
jint
argc
,
jbyteArray
argBlock
,
jint
argc
,
jbyteArray
envBlock
,
jint
envc
,
jbyteArray
envBlock
,
jint
envc
,
jbyteArray
dir
,
jbyteArray
dir
,
jboolean
redirectErrorStream
,
jintArray
std_fds
,
jobject
stdin_fd
,
jboolean
redirectErrorStream
)
jobject
stdout_fd
,
jobject
stderr_fd
)
{
{
int
errnum
;
int
errnum
;
int
resultPid
=
-
1
;
int
resultPid
=
-
1
;
...
@@ -505,6 +534,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -505,6 +534,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
const
char
*
pargBlock
=
getBytes
(
env
,
argBlock
);
const
char
*
pargBlock
=
getBytes
(
env
,
argBlock
);
const
char
*
penvBlock
=
getBytes
(
env
,
envBlock
);
const
char
*
penvBlock
=
getBytes
(
env
,
envBlock
);
const
char
*
pdir
=
getBytes
(
env
,
dir
);
const
char
*
pdir
=
getBytes
(
env
,
dir
);
jint
*
fds
=
NULL
;
in
[
0
]
=
in
[
1
]
=
out
[
0
]
=
out
[
1
]
=
err
[
0
]
=
err
[
1
]
=
fail
[
0
]
=
fail
[
1
]
=
-
1
;
in
[
0
]
=
in
[
1
]
=
out
[
0
]
=
out
[
1
]
=
err
[
0
]
=
err
[
1
]
=
fail
[
0
]
=
fail
[
1
]
=
-
1
;
...
@@ -527,9 +557,13 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -527,9 +557,13 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
initVectorFromBlock
(
envv
,
penvBlock
,
envc
);
initVectorFromBlock
(
envv
,
penvBlock
,
envc
);
}
}
if
((
pipe
(
in
)
<
0
)
||
assert
(
std_fds
!=
NULL
);
(
pipe
(
out
)
<
0
)
||
fds
=
(
*
env
)
->
GetIntArrayElements
(
env
,
std_fds
,
NULL
);
(
pipe
(
err
)
<
0
)
||
if
(
fds
==
NULL
)
goto
Catch
;
if
((
fds
[
0
]
==
-
1
&&
pipe
(
in
)
<
0
)
||
(
fds
[
1
]
==
-
1
&&
pipe
(
out
)
<
0
)
||
(
fds
[
2
]
==
-
1
&&
pipe
(
err
)
<
0
)
||
(
pipe
(
fail
)
<
0
))
{
(
pipe
(
fail
)
<
0
))
{
throwIOException
(
env
,
errno
,
"Bad file descriptor"
);
throwIOException
(
env
,
errno
,
"Bad file descriptor"
);
goto
Catch
;
goto
Catch
;
...
@@ -544,23 +578,26 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -544,23 +578,26 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
if
(
resultPid
==
0
)
{
if
(
resultPid
==
0
)
{
/* Child process */
/* Child process */
/* Close the parent sides of the pipe.
/* Close the parent sides of the pipes.
Give the child sides of the pipes the right fileno's.
Closing pipe fds here is redundant, since closeDescriptors()
Closing pipe fds here is redundant, since closeDescriptors()
would do it anyways, but a little paranoia is a good thing. */
would do it anyways, but a little paranoia is a good thing. */
closeSafely
(
in
[
1
]);
closeSafely
(
out
[
0
]);
closeSafely
(
err
[
0
]);
closeSafely
(
fail
[
0
]);
/* Give the child sides of the pipes the right fileno's. */
/* Note: it is possible for in[0] == 0 */
/* Note: it is possible for in[0] == 0 */
close
(
in
[
1
]);
moveDescriptor
(
in
[
0
]
!=
-
1
?
in
[
0
]
:
fds
[
0
],
STDIN_FILENO
);
moveDescriptor
(
in
[
0
],
STDIN_FILENO
);
moveDescriptor
(
out
[
1
]
!=
-
1
?
out
[
1
]
:
fds
[
1
],
STDOUT_FILENO
);
close
(
out
[
0
]);
moveDescriptor
(
out
[
1
],
STDOUT_FILENO
);
close
(
err
[
0
]);
if
(
redirectErrorStream
)
{
if
(
redirectErrorStream
)
{
close
(
err
[
1
]);
close
Safely
(
err
[
1
]);
dup2
(
STDOUT_FILENO
,
STDERR_FILENO
);
dup2
(
STDOUT_FILENO
,
STDERR_FILENO
);
}
else
{
}
else
{
moveDescriptor
(
err
[
1
],
STDERR_FILENO
);
moveDescriptor
(
err
[
1
]
!=
-
1
?
err
[
1
]
:
fds
[
2
]
,
STDERR_FILENO
);
}
}
close
(
fail
[
0
]);
moveDescriptor
(
fail
[
1
],
FAIL_FILENO
);
moveDescriptor
(
fail
[
1
],
FAIL_FILENO
);
/* close everything */
/* close everything */
...
@@ -600,15 +637,21 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -600,15 +637,21 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
/* parent process */
/* parent process */
close
(
fail
[
1
]);
fail
[
1
]
=
-
1
;
/* See: WhyCantJohnnyExec */
close
(
fail
[
1
]);
fail
[
1
]
=
-
1
;
/* See: WhyCantJohnnyExec */
if
(
read
(
fail
[
0
],
&
errnum
,
sizeof
(
errnum
))
!=
0
)
{
switch
(
readFully
(
fail
[
0
],
&
errnum
,
sizeof
(
errnum
)))
{
case
0
:
break
;
/* Exec succeeded */
case
sizeof
(
errnum
):
waitpid
(
resultPid
,
NULL
,
0
);
waitpid
(
resultPid
,
NULL
,
0
);
throwIOException
(
env
,
errnum
,
"Exec failed"
);
throwIOException
(
env
,
errnum
,
"Exec failed"
);
goto
Catch
;
goto
Catch
;
default:
throwIOException
(
env
,
errno
,
"Read failed"
);
goto
Catch
;
}
}
(
*
env
)
->
SetIntField
(
env
,
stdin_fd
,
IO_fd_fdID
,
in
[
1
])
;
fds
[
0
]
=
(
in
[
1
]
!=
-
1
)
?
in
[
1
]
:
-
1
;
(
*
env
)
->
SetIntField
(
env
,
stdout_fd
,
IO_fd_fdID
,
out
[
0
])
;
fds
[
1
]
=
(
out
[
0
]
!=
-
1
)
?
out
[
0
]
:
-
1
;
(
*
env
)
->
SetIntField
(
env
,
stderr_fd
,
IO_fd_fdID
,
err
[
0
])
;
fds
[
2
]
=
(
err
[
0
]
!=
-
1
)
?
err
[
0
]
:
-
1
;
Finally:
Finally:
/* Always clean up the child's side of the pipes */
/* Always clean up the child's side of the pipes */
...
@@ -628,6 +671,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -628,6 +671,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
releaseBytes
(
env
,
envBlock
,
penvBlock
);
releaseBytes
(
env
,
envBlock
,
penvBlock
);
releaseBytes
(
env
,
dir
,
pdir
);
releaseBytes
(
env
,
dir
,
pdir
);
if
(
fds
!=
NULL
)
(
*
env
)
->
ReleaseIntArrayElements
(
env
,
std_fds
,
fds
,
0
);
return
resultPid
;
return
resultPid
;
Catch:
Catch:
...
...
src/windows/classes/java/io/FileDescriptor.java
浏览文件 @
73d65ed1
...
@@ -29,17 +29,14 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -29,17 +29,14 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
/**
* Instances of the file descriptor class serve as an opaque handle
* Instances of the file descriptor class serve as an opaque handle
* to the underlying machine-specific structure representing an open
* to the underlying machine-specific structure representing an
* file, an open socket, or another source or sink of bytes. The
* open file, an open socket, or another source or sink of bytes.
* main practical use for a file descriptor is to create a
* The main practical use for a file descriptor is to create a
* <code>FileInputStream</code> or <code>FileOutputStream</code> to
* {@link FileInputStream} or {@link FileOutputStream} to contain it.
* contain it.
*
* <p>
* <p>Applications should not create their own file descriptors.
* Applications should not create their own file descriptors.
*
*
* @author Pavani Diwanji
* @author Pavani Diwanji
* @see java.io.FileInputStream
* @see java.io.FileOutputStream
* @since JDK1.0
* @since JDK1.0
*/
*/
public
final
class
FileDescriptor
{
public
final
class
FileDescriptor
{
...
@@ -81,6 +78,14 @@ public final class FileDescriptor {
...
@@ -81,6 +78,14 @@ public final class FileDescriptor {
public
int
get
(
FileDescriptor
obj
)
{
public
int
get
(
FileDescriptor
obj
)
{
return
obj
.
fd
;
return
obj
.
fd
;
}
}
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
)
{
obj
.
handle
=
handle
;
}
public
long
getHandle
(
FileDescriptor
obj
)
{
return
obj
.
handle
;
}
}
}
);
);
}
}
...
@@ -88,7 +93,7 @@ public final class FileDescriptor {
...
@@ -88,7 +93,7 @@ public final class FileDescriptor {
/**
/**
* A handle to the standard input stream. Usually, this file
* A handle to the standard input stream. Usually, this file
* descriptor is not used directly, but rather via the input stream
* descriptor is not used directly, but rather via the input stream
* known as
<code>System.in</code>
.
* known as
{@code System.in}
.
*
*
* @see java.lang.System#in
* @see java.lang.System#in
*/
*/
...
@@ -97,7 +102,7 @@ public final class FileDescriptor {
...
@@ -97,7 +102,7 @@ public final class FileDescriptor {
/**
/**
* A handle to the standard output stream. Usually, this file
* A handle to the standard output stream. Usually, this file
* descriptor is not used directly, but rather via the output stream
* descriptor is not used directly, but rather via the output stream
* known as
<code>System.out</code>
.
* known as
{@code System.out}
.
* @see java.lang.System#out
* @see java.lang.System#out
*/
*/
public
static
final
FileDescriptor
out
=
standardStream
(
1
);
public
static
final
FileDescriptor
out
=
standardStream
(
1
);
...
@@ -105,7 +110,7 @@ public final class FileDescriptor {
...
@@ -105,7 +110,7 @@ public final class FileDescriptor {
/**
/**
* A handle to the standard error stream. Usually, this file
* A handle to the standard error stream. Usually, this file
* descriptor is not used directly, but rather via the output stream
* descriptor is not used directly, but rather via the output stream
* known as
<code>System.err</code>
.
* known as
{@code System.err}
.
*
*
* @see java.lang.System#err
* @see java.lang.System#err
*/
*/
...
@@ -114,9 +119,9 @@ public final class FileDescriptor {
...
@@ -114,9 +119,9 @@ public final class FileDescriptor {
/**
/**
* Tests if this file descriptor object is valid.
* Tests if this file descriptor object is valid.
*
*
* @return
<code>true</code>
if the file descriptor object represents a
* @return
{@code true}
if the file descriptor object represents a
* valid, open file, socket, or other active I/O connection;
* valid, open file, socket, or other active I/O connection;
*
<code>false</code>
otherwise.
*
{@code false}
otherwise.
*/
*/
public
boolean
valid
()
{
public
boolean
valid
()
{
return
((
handle
!=
-
1
)
||
(
fd
!=
-
1
));
return
((
handle
!=
-
1
)
||
(
fd
!=
-
1
));
...
...
src/windows/classes/java/lang/ProcessImpl.java
浏览文件 @
73d65ed1
...
@@ -25,7 +25,16 @@
...
@@ -25,7 +25,16 @@
package
java.lang
;
package
java.lang
;
import
java.io.*
;
import
java.io.IOException
;
import
java.io.File
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.FileDescriptor
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.lang.ProcessBuilder.Redirect
;
/* This class is for the exclusive use of ProcessBuilder.start() to
/* This class is for the exclusive use of ProcessBuilder.start() to
* create new processes.
* create new processes.
...
@@ -35,30 +44,82 @@ import java.io.*;
...
@@ -35,30 +44,82 @@ import java.io.*;
*/
*/
final
class
ProcessImpl
extends
Process
{
final
class
ProcessImpl
extends
Process
{
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
();
// System-dependent portion of ProcessBuilder.start()
// System-dependent portion of ProcessBuilder.start()
static
Process
start
(
String
cmdarray
[],
static
Process
start
(
String
cmdarray
[],
java
.
util
.
Map
<
String
,
String
>
environment
,
java
.
util
.
Map
<
String
,
String
>
environment
,
String
dir
,
String
dir
,
ProcessBuilder
.
Redirect
[]
redirects
,
boolean
redirectErrorStream
)
boolean
redirectErrorStream
)
throws
IOException
throws
IOException
{
{
String
envblock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
);
String
envblock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
);
return
new
ProcessImpl
(
cmdarray
,
envblock
,
dir
,
redirectErrorStream
);
FileInputStream
f0
=
null
;
FileOutputStream
f1
=
null
;
FileOutputStream
f2
=
null
;
try
{
long
[]
stdHandles
;
if
(
redirects
==
null
)
{
stdHandles
=
new
long
[]
{
-
1L
,
-
1L
,
-
1L
};
}
else
{
stdHandles
=
new
long
[
3
];
if
(
redirects
[
0
]
==
Redirect
.
PIPE
)
stdHandles
[
0
]
=
-
1L
;
else
if
(
redirects
[
0
]
==
Redirect
.
INHERIT
)
stdHandles
[
0
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
in
);
else
{
f0
=
new
FileInputStream
(
redirects
[
0
].
file
());
stdHandles
[
0
]
=
fdAccess
.
getHandle
(
f0
.
getFD
());
}
if
(
redirects
[
1
]
==
Redirect
.
PIPE
)
stdHandles
[
1
]
=
-
1L
;
else
if
(
redirects
[
1
]
==
Redirect
.
INHERIT
)
stdHandles
[
1
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
out
);
else
{
f1
=
redirects
[
1
].
toFileOutputStream
();
stdHandles
[
1
]
=
fdAccess
.
getHandle
(
f1
.
getFD
());
}
if
(
redirects
[
2
]
==
Redirect
.
PIPE
)
stdHandles
[
2
]
=
-
1L
;
else
if
(
redirects
[
2
]
==
Redirect
.
INHERIT
)
stdHandles
[
2
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
err
);
else
{
f2
=
redirects
[
2
].
toFileOutputStream
();
stdHandles
[
2
]
=
fdAccess
.
getHandle
(
f2
.
getFD
());
}
}
return
new
ProcessImpl
(
cmdarray
,
envblock
,
dir
,
stdHandles
,
redirectErrorStream
);
}
finally
{
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
try
{
if
(
f0
!=
null
)
f0
.
close
();
}
finally
{
try
{
if
(
f1
!=
null
)
f1
.
close
();
}
finally
{
if
(
f2
!=
null
)
f2
.
close
();
}
}
}
}
}
private
long
handle
=
0
;
private
long
handle
=
0
;
private
FileDescriptor
stdin_fd
;
private
FileDescriptor
stdout_fd
;
private
FileDescriptor
stderr_fd
;
private
OutputStream
stdin_stream
;
private
OutputStream
stdin_stream
;
private
InputStream
stdout_stream
;
private
InputStream
stdout_stream
;
private
InputStream
stderr_stream
;
private
InputStream
stderr_stream
;
private
ProcessImpl
(
String
cmd
[],
private
ProcessImpl
(
final
String
cmd
[],
String
envblock
,
final
String
envblock
,
String
path
,
final
String
path
,
boolean
redirectErrorStream
)
final
long
[]
stdHandles
,
final
boolean
redirectErrorStream
)
throws
IOException
throws
IOException
{
{
// Win32 CreateProcess requires cmd[0] to be normalized
// Win32 CreateProcess requires cmd[0] to be normalized
...
@@ -91,25 +152,39 @@ final class ProcessImpl extends Process {
...
@@ -91,25 +152,39 @@ final class ProcessImpl extends Process {
}
}
String
cmdstr
=
cmdbuf
.
toString
();
String
cmdstr
=
cmdbuf
.
toString
();
stdin_fd
=
new
FileDescriptor
();
handle
=
create
(
cmdstr
,
envblock
,
path
,
stdout_fd
=
new
FileDescriptor
();
stdHandles
,
redirectErrorStream
);
stderr_fd
=
new
FileDescriptor
();
handle
=
create
(
cmdstr
,
envblock
,
path
,
redirectErrorStream
,
stdin_fd
,
stdout_fd
,
stderr_fd
);
java
.
security
.
AccessController
.
doPrivileged
(
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
()
{
new
java
.
security
.
PrivilegedAction
<
Void
>
()
{
public
Object
run
()
{
public
Void
run
()
{
stdin_stream
=
if
(
stdHandles
[
0
]
==
-
1L
)
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
)
);
stdin_stream
=
new
ProcessBuilder
.
NullOutputStream
(
);
stdout_stream
=
else
{
new
BufferedInputStream
(
new
FileInputStream
(
stdout_fd
)
);
FileDescriptor
stdin_fd
=
new
FileDescriptor
(
);
stderr_stream
=
fdAccess
.
setHandle
(
stdin_fd
,
stdHandles
[
0
]);
new
FileInputStream
(
stderr_fd
);
stdin_stream
=
new
BufferedOutputStream
(
return
null
;
new
FileOutputStream
(
stdin_fd
))
;
}
}
});
if
(
stdHandles
[
1
]
==
-
1L
)
stdout_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stdout_fd
=
new
FileDescriptor
();
fdAccess
.
setHandle
(
stdout_fd
,
stdHandles
[
1
]);
stdout_stream
=
new
BufferedInputStream
(
new
FileInputStream
(
stdout_fd
));
}
if
(
stdHandles
[
2
]
==
-
1L
)
stderr_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stderr_fd
=
new
FileDescriptor
();
fdAccess
.
setHandle
(
stderr_fd
,
stdHandles
[
2
]);
stderr_stream
=
new
FileInputStream
(
stderr_fd
);
}
return
null
;
}});
}
}
public
OutputStream
getOutputStream
()
{
public
OutputStream
getOutputStream
()
{
...
@@ -150,13 +225,30 @@ final class ProcessImpl extends Process {
...
@@ -150,13 +225,30 @@ final class ProcessImpl extends Process {
public
void
destroy
()
{
terminateProcess
(
handle
);
}
public
void
destroy
()
{
terminateProcess
(
handle
);
}
private
static
native
void
terminateProcess
(
long
handle
);
private
static
native
void
terminateProcess
(
long
handle
);
/**
* Create a process using the win32 function CreateProcess.
*
* @param cmdstr the Windows commandline
* @param envblock NUL-separated, double-NUL-terminated list of
* environment strings in VAR=VALUE form
* @param dir the working directory of the process, or null if
* inheriting the current directory from the parent process
* @param stdHandles array of windows HANDLEs. Indexes 0, 1, and
* 2 correspond to standard input, standard output and
* standard error, respectively. On input, a value of -1
* means to create a pipe to connect child and parent
* processes. On output, a value which is not -1 is the
* parent pipe handle corresponding to the pipe which has
* been created. An element of this array is -1 on input
* if and only if it is <em>not</em> -1 on output.
* @param redirectErrorStream redirectErrorStream attribute
* @return the native subprocess HANDLE returned by CreateProcess
*/
private
static
native
long
create
(
String
cmdstr
,
private
static
native
long
create
(
String
cmdstr
,
String
envblock
,
String
envblock
,
String
dir
,
String
dir
,
boolean
redirectErrorStream
,
long
[]
stdHandles
,
FileDescriptor
in_fd
,
boolean
redirectErrorStream
)
FileDescriptor
out_fd
,
FileDescriptor
err_fd
)
throws
IOException
;
throws
IOException
;
private
static
native
boolean
closeHandle
(
long
handle
);
private
static
native
boolean
closeHandle
(
long
handle
);
...
...
src/windows/native/java/io/FileOutputStream_md.c
浏览文件 @
73d65ed1
...
@@ -39,8 +39,6 @@
...
@@ -39,8 +39,6 @@
jfieldID
fos_fd
;
/* id for jobject 'fd' in java.io.FileOutputStream */
jfieldID
fos_fd
;
/* id for jobject 'fd' in java.io.FileOutputStream */
jfieldID
fos_append
;
/**************************************************************
/**************************************************************
* static methods to store field ID's in initializers
* static methods to store field ID's in initializers
*/
*/
...
@@ -49,7 +47,6 @@ JNIEXPORT void JNICALL
...
@@ -49,7 +47,6 @@ JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_initIDs
(
JNIEnv
*
env
,
jclass
fosClass
)
{
Java_java_io_FileOutputStream_initIDs
(
JNIEnv
*
env
,
jclass
fosClass
)
{
fos_fd
=
fos_fd
=
(
*
env
)
->
GetFieldID
(
env
,
fosClass
,
"fd"
,
"Ljava/io/FileDescriptor;"
);
(
*
env
)
->
GetFieldID
(
env
,
fosClass
,
"fd"
,
"Ljava/io/FileDescriptor;"
);
fos_append
=
(
*
env
)
->
GetFieldID
(
env
,
fosClass
,
"append"
,
"Z"
);
}
}
/**************************************************************
/**************************************************************
...
@@ -57,45 +54,20 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fosClass) {
...
@@ -57,45 +54,20 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fosClass) {
*/
*/
JNIEXPORT
void
JNICALL
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
);
jstring
path
,
jboolean
append
)
{
}
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
(
append
?
O_APPEND
:
O_TRUNC
));
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_openAppend
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
}
}
JNIEXPORT
void
JNICALL
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_write
(
JNIEnv
*
env
,
jobject
this
,
jint
byte
)
{
Java_java_io_FileOutputStream_write
(
JNIEnv
*
env
,
jobject
this
,
jint
byte
)
{
jboolean
append
=
(
*
env
)
->
GetBooleanField
(
env
,
this
,
fos_append
);
FD
fd
=
GET_FD
(
this
,
fos_fd
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
}
if
(
append
==
JNI_TRUE
)
{
if
(
IO_Lseek
(
fd
,
0L
,
SEEK_END
)
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"Append failed"
);
}
}
writeSingle
(
env
,
this
,
byte
,
fos_fd
);
writeSingle
(
env
,
this
,
byte
,
fos_fd
);
}
}
JNIEXPORT
void
JNICALL
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_writeBytes
(
JNIEnv
*
env
,
Java_java_io_FileOutputStream_writeBytes
(
JNIEnv
*
env
,
jobject
this
,
jbyteArray
bytes
,
jint
off
,
jint
len
)
{
jobject
this
,
jbyteArray
bytes
,
jint
off
,
jint
len
)
{
jboolean
append
=
(
*
env
)
->
GetBooleanField
(
env
,
this
,
fos_append
);
FD
fd
=
GET_FD
(
this
,
fos_fd
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
}
if
(
append
==
JNI_TRUE
)
{
if
(
IO_Lseek
(
fd
,
0L
,
SEEK_END
)
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"Append failed"
);
}
}
writeBytes
(
env
,
this
,
bytes
,
off
,
len
,
fos_fd
);
writeBytes
(
env
,
this
,
bytes
,
off
,
len
,
fos_fd
);
}
}
...
...
src/windows/native/java/io/io_util_md.c
浏览文件 @
73d65ed1
...
@@ -42,7 +42,7 @@
...
@@ -42,7 +42,7 @@
extern
jboolean
onNT
=
JNI_FALSE
;
extern
jboolean
onNT
=
JNI_FALSE
;
static
int
MAX_INPUT_EVENTS
=
2000
;
static
DWORD
MAX_INPUT_EVENTS
=
2000
;
void
void
initializeWindowsVersion
()
{
initializeWindowsVersion
()
{
...
@@ -190,9 +190,16 @@ pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) {
...
@@ -190,9 +190,16 @@ pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) {
jlong
jlong
winFileHandleOpen
(
JNIEnv
*
env
,
jstring
path
,
int
flags
)
winFileHandleOpen
(
JNIEnv
*
env
,
jstring
path
,
int
flags
)
{
{
/* To implement O_APPEND, we use the strategy from
http://msdn2.microsoft.com/en-us/library/aa363858.aspx
"You can get atomic append by opening a file with
FILE_APPEND_DATA access and _without_ FILE_WRITE_DATA access.
If you do this then all writes will ignore the current file
pointer and be done at the end-of file." */
const
DWORD
access
=
const
DWORD
access
=
(
flags
&
O_
RDWR
)
?
(
GENERIC_WRITE
|
GENERIC_READ
)
:
(
flags
&
O_
APPEND
)
?
(
FILE_GENERIC_WRITE
&
~
FILE_WRITE_DATA
)
:
(
flags
&
O_WRONLY
)
?
GENERIC_WRITE
:
(
flags
&
O_WRONLY
)
?
GENERIC_WRITE
:
(
flags
&
O_RDWR
)
?
(
GENERIC_READ
|
GENERIC_WRITE
)
:
GENERIC_READ
;
GENERIC_READ
;
const
DWORD
sharing
=
const
DWORD
sharing
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
...
@@ -444,24 +451,6 @@ handleSetLength(jlong fd, jlong length) {
...
@@ -444,24 +451,6 @@ handleSetLength(jlong fd, jlong length) {
return
0
;
return
0
;
}
}
int
handleFileSizeFD
(
jlong
fd
,
jlong
*
size
)
{
DWORD
sizeLow
=
0
;
DWORD
sizeHigh
=
0
;
HANDLE
h
=
(
HANDLE
)
fd
;
if
(
h
==
INVALID_HANDLE_VALUE
)
{
return
-
1
;
}
sizeLow
=
GetFileSize
(
h
,
&
sizeHigh
);
if
(
sizeLow
==
((
DWORD
)
-
1
))
{
if
(
GetLastError
()
!=
ERROR_SUCCESS
)
{
return
-
1
;
}
}
return
(((
jlong
)
sizeHigh
)
<<
32
)
|
sizeLow
;
}
JNIEXPORT
JNIEXPORT
size_t
size_t
handleRead
(
jlong
fd
,
void
*
buf
,
jint
len
)
handleRead
(
jlong
fd
,
void
*
buf
,
jint
len
)
...
@@ -513,7 +502,7 @@ handleClose(JNIEnv *env, jobject this, jfieldID fid)
...
@@ -513,7 +502,7 @@ handleClose(JNIEnv *env, jobject this, jfieldID fid)
FD
fd
=
GET_FD
(
this
,
fid
);
FD
fd
=
GET_FD
(
this
,
fid
);
HANDLE
h
=
(
HANDLE
)
fd
;
HANDLE
h
=
(
HANDLE
)
fd
;
if
(
fd
==
INVALID_HANDLE_VALUE
)
{
if
(
h
==
INVALID_HANDLE_VALUE
)
{
return
0
;
return
0
;
}
}
...
...
src/windows/native/java/io/io_util_md.h
浏览文件 @
73d65ed1
...
@@ -38,7 +38,6 @@ void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
...
@@ -38,7 +38,6 @@ void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
int
handleAvailable
(
jlong
fd
,
jlong
*
pbytes
);
int
handleAvailable
(
jlong
fd
,
jlong
*
pbytes
);
JNIEXPORT
int
handleSync
(
jlong
fd
);
JNIEXPORT
int
handleSync
(
jlong
fd
);
int
handleSetLength
(
jlong
fd
,
jlong
length
);
int
handleSetLength
(
jlong
fd
,
jlong
length
);
int
handleFileSizeFD
(
jlong
fd
,
jlong
*
size
);
JNIEXPORT
size_t
handleRead
(
jlong
fd
,
void
*
buf
,
jint
len
);
JNIEXPORT
size_t
handleRead
(
jlong
fd
,
void
*
buf
,
jint
len
);
JNIEXPORT
size_t
handleWrite
(
jlong
fd
,
const
void
*
buf
,
jint
len
);
JNIEXPORT
size_t
handleWrite
(
jlong
fd
,
const
void
*
buf
,
jint
len
);
jint
handleClose
(
JNIEnv
*
env
,
jobject
this
,
jfieldID
fid
);
jint
handleClose
(
JNIEnv
*
env
,
jobject
this
,
jfieldID
fid
);
...
...
src/windows/native/java/lang/ProcessImpl_md.c
浏览文件 @
73d65ed1
...
@@ -33,7 +33,12 @@
...
@@ -33,7 +33,12 @@
#include <windows.h>
#include <windows.h>
#include <io.h>
#include <io.h>
#define PIPE_SIZE 4096
/* We try to make sure that we can read and write 4095 bytes (the
* fixed limit on Linux) to the pipe on all operating systems without
* deadlock. Windows 2000 inexplicably appears to need an extra 24
* bytes of slop to avoid deadlock.
*/
#define PIPE_SIZE (4096+24)
char
*
char
*
extractExecutablePath
(
JNIEnv
*
env
,
char
*
source
)
extractExecutablePath
(
JNIEnv
*
env
,
char
*
source
)
...
@@ -120,7 +125,7 @@ win32Error(JNIEnv *env, const char *functionName)
...
@@ -120,7 +125,7 @@ win32Error(JNIEnv *env, const char *functionName)
static
void
static
void
closeSafely
(
HANDLE
handle
)
closeSafely
(
HANDLE
handle
)
{
{
if
(
handle
)
if
(
handle
!=
INVALID_HANDLE_VALUE
)
CloseHandle
(
handle
);
CloseHandle
(
handle
);
}
}
...
@@ -129,23 +134,22 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -129,23 +134,22 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
jstring
cmd
,
jstring
cmd
,
jstring
envBlock
,
jstring
envBlock
,
jstring
dir
,
jstring
dir
,
jboolean
redirectErrorStream
,
jlongArray
stdHandles
,
jobject
in_fd
,
jboolean
redirectErrorStream
)
jobject
out_fd
,
jobject
err_fd
)
{
{
HANDLE
inRead
=
0
;
HANDLE
inRead
=
INVALID_HANDLE_VALUE
;
HANDLE
inWrite
=
0
;
HANDLE
inWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
outRead
=
0
;
HANDLE
outRead
=
INVALID_HANDLE_VALUE
;
HANDLE
outWrite
=
0
;
HANDLE
outWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
errRead
=
0
;
HANDLE
errRead
=
INVALID_HANDLE_VALUE
;
HANDLE
errWrite
=
0
;
HANDLE
errWrite
=
INVALID_HANDLE_VALUE
;
SECURITY_ATTRIBUTES
sa
;
SECURITY_ATTRIBUTES
sa
;
PROCESS_INFORMATION
pi
;
PROCESS_INFORMATION
pi
;
STARTUPINFO
si
;
STARTUPINFO
si
;
LPTSTR
pcmd
=
NULL
;
LPTSTR
pcmd
=
NULL
;
LPCTSTR
pdir
=
NULL
;
LPCTSTR
pdir
=
NULL
;
LPVOID
penvBlock
=
NULL
;
LPVOID
penvBlock
=
NULL
;
jlong
*
handles
=
NULL
;
jlong
ret
=
0
;
jlong
ret
=
0
;
OSVERSIONINFO
ver
;
OSVERSIONINFO
ver
;
jboolean
onNT
=
JNI_FALSE
;
jboolean
onNT
=
JNI_FALSE
;
...
@@ -156,17 +160,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -156,17 +160,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if
(
ver
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
if
(
ver
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
onNT
=
JNI_TRUE
;
onNT
=
JNI_TRUE
;
sa
.
nLength
=
sizeof
(
sa
);
sa
.
lpSecurityDescriptor
=
0
;
sa
.
bInheritHandle
=
TRUE
;
if
(
!
(
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
)
&&
CreatePipe
(
&
outRead
,
&
outWrite
,
&
sa
,
PIPE_SIZE
)
&&
CreatePipe
(
&
errRead
,
&
errWrite
,
&
sa
,
PIPE_SIZE
)))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
assert
(
cmd
!=
NULL
);
assert
(
cmd
!=
NULL
);
pcmd
=
(
LPTSTR
)
JNU_GetStringPlatformChars
(
env
,
cmd
,
NULL
);
pcmd
=
(
LPTSTR
)
JNU_GetStringPlatformChars
(
env
,
cmd
,
NULL
);
if
(
pcmd
==
NULL
)
goto
Catch
;
if
(
pcmd
==
NULL
)
goto
Catch
;
...
@@ -184,19 +177,62 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -184,19 +177,62 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if
(
penvBlock
==
NULL
)
goto
Catch
;
if
(
penvBlock
==
NULL
)
goto
Catch
;
}
}
assert
(
stdHandles
!=
NULL
);
handles
=
(
*
env
)
->
GetLongArrayElements
(
env
,
stdHandles
,
NULL
);
if
(
handles
==
NULL
)
goto
Catch
;
memset
(
&
si
,
0
,
sizeof
(
si
));
memset
(
&
si
,
0
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
si
.
cb
=
sizeof
(
si
);
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
si
.
hStdInput
=
inRead
;
si
.
hStdOutput
=
outWrite
;
si
.
hStdError
=
redirectErrorStream
?
outWrite
:
errWrite
;
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
sa
.
nLength
=
sizeof
(
sa
);
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
FALSE
)
;
sa
.
lpSecurityDescriptor
=
0
;
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
FALSE
)
;
sa
.
bInheritHandle
=
TRUE
;
if
(
redirectErrorStream
)
if
(
handles
[
0
]
!=
(
jlong
)
-
1
)
{
SetHandleInformation
(
errWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
si
.
hStdInput
=
(
HANDLE
)
handles
[
0
];
handles
[
0
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdInput
=
inRead
;
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
0
]
=
(
jlong
)
inWrite
;
}
SetHandleInformation
(
si
.
hStdInput
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
handles
[
1
]
!=
(
jlong
)
-
1
)
{
si
.
hStdOutput
=
(
HANDLE
)
handles
[
1
];
handles
[
1
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
outRead
,
&
outWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdOutput
=
outWrite
;
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
1
]
=
(
jlong
)
outRead
;
}
SetHandleInformation
(
si
.
hStdOutput
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
redirectErrorStream
)
{
si
.
hStdError
=
si
.
hStdOutput
;
handles
[
2
]
=
(
jlong
)
-
1
;
}
else
if
(
handles
[
2
]
!=
(
jlong
)
-
1
)
{
si
.
hStdError
=
(
HANDLE
)
handles
[
2
];
handles
[
2
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
errRead
,
&
errWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdError
=
errWrite
;
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
2
]
=
(
jlong
)
errRead
;
}
SetHandleInformation
(
si
.
hStdError
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
onNT
)
if
(
onNT
)
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
...
@@ -232,9 +268,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -232,9 +268,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hThread
);
ret
=
(
jlong
)
pi
.
hProcess
;
ret
=
(
jlong
)
pi
.
hProcess
;
(
*
env
)
->
SetLongField
(
env
,
in_fd
,
IO_handle_fdID
,
(
jlong
)
inWrite
);
(
*
env
)
->
SetLongField
(
env
,
out_fd
,
IO_handle_fdID
,
(
jlong
)
outRead
);
(
*
env
)
->
SetLongField
(
env
,
err_fd
,
IO_handle_fdID
,
(
jlong
)
errRead
);
Finally:
Finally:
/* Always clean up the child's side of the pipes */
/* Always clean up the child's side of the pipes */
...
@@ -252,6 +285,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -252,6 +285,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
else
else
JNU_ReleaseStringPlatformChars
(
env
,
dir
,
(
char
*
)
penvBlock
);
JNU_ReleaseStringPlatformChars
(
env
,
dir
,
(
char
*
)
penvBlock
);
}
}
if
(
handles
!=
NULL
)
(
*
env
)
->
ReleaseLongArrayElements
(
env
,
stdHandles
,
handles
,
0
);
return
ret
;
return
ret
;
Catch:
Catch:
...
...
src/windows/native/java/lang/java_props_md.c
浏览文件 @
73d65ed1
...
@@ -673,13 +673,13 @@ GetJavaProperties(JNIEnv* env)
...
@@ -673,13 +673,13 @@ GetJavaProperties(JNIEnv* env)
/* OS properties */
/* OS properties */
{
{
char
buf
[
100
];
char
buf
[
100
];
OSVERSIONINFO
ver
;
OSVERSIONINFO
EX
ver
;
ver
.
dwOSVersionInfoSize
=
sizeof
(
ver
);
ver
.
dwOSVersionInfoSize
=
sizeof
(
ver
);
GetVersionEx
(
&
ver
);
GetVersionEx
(
(
OSVERSIONINFO
*
)
&
ver
);
/*
/*
* From msdn page on OSVERSIONINFOEX, current as of this
* From msdn page on OSVERSIONINFOEX, current as of this
* writing decoding of dwMajorVersion and dwMinorVersion.
* writing
,
decoding of dwMajorVersion and dwMinorVersion.
*
*
* Operating system dwMajorVersion dwMinorVersion
* Operating system dwMajorVersion dwMinorVersion
* ================== ============== ==============
* ================== ============== ==============
...
@@ -692,7 +692,7 @@ GetJavaProperties(JNIEnv* env)
...
@@ -692,7 +692,7 @@ GetJavaProperties(JNIEnv* env)
* Windows 2000 5 0
* Windows 2000 5 0
* Windows XP 5 1
* Windows XP 5 1
* Windows Server 2003 family 5 2
* Windows Server 2003 family 5 2
* Windows Vista
6 0
* Windows Vista
family
6 0
*
*
* This mapping will presumably be augmented as new Windows
* This mapping will presumably be augmented as new Windows
* versions are released.
* versions are released.
...
@@ -724,7 +724,20 @@ GetJavaProperties(JNIEnv* env)
...
@@ -724,7 +724,20 @@ GetJavaProperties(JNIEnv* env)
default:
sprops
.
os_name
=
"Windows NT (unknown)"
;
break
;
default:
sprops
.
os_name
=
"Windows NT (unknown)"
;
break
;
}
}
}
else
if
(
ver
.
dwMajorVersion
==
6
)
{
}
else
if
(
ver
.
dwMajorVersion
==
6
)
{
sprops
.
os_name
=
"Windows Vista"
;
/*
* From MSDN OSVERSIONINFOEX documentation:
*
* "Because the version numbers for Windows Server 2008
* and Windows Vista are identical, you must also test
* whether the wProductType member is VER_NT_WORKSTATION.
* If wProductType is VER_NT_WORKSTATION, the operating
* system is Windows Vista; otherwise, it is Windows
* Server 2008."
*/
if
(
ver
.
wProductType
==
VER_NT_WORKSTATION
)
sprops
.
os_name
=
"Windows Vista"
;
else
sprops
.
os_name
=
"Windows Server 2008"
;
}
else
{
}
else
{
sprops
.
os_name
=
"Windows NT (unknown)"
;
sprops
.
os_name
=
"Windows NT (unknown)"
;
}
}
...
...
test/java/io/FileOutputStream/AtomicAppend.java
0 → 100644
浏览文件 @
73d65ed1
/*
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6631352
* @summary Check that appends are atomic
*/
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.TimeUnit
;
public
class
AtomicAppend
{
// Before the fix for
// 6631352: Implement atomic append mode using FILE_APPEND_DATA (win)
// this would fail intermittently on windows
void
test
(
String
[]
args
)
throws
Throwable
{
final
int
nThreads
=
10
;
final
int
writes
=
1000
;
final
File
file
=
new
File
(
"foo"
);
file
.
delete
();
try
{
final
ExecutorService
es
=
Executors
.
newFixedThreadPool
(
nThreads
);
for
(
int
i
=
0
;
i
<
nThreads
;
i
++)
es
.
execute
(
new
Runnable
()
{
public
void
run
()
{
try
{
FileOutputStream
s
=
new
FileOutputStream
(
file
,
true
);
for
(
int
j
=
0
;
j
<
1000
;
j
++)
{
s
.
write
((
int
)
'x'
);
s
.
flush
();
}
s
.
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}}});
es
.
shutdown
();
es
.
awaitTermination
(
10L
,
TimeUnit
.
MINUTES
);
equal
(
file
.
length
(),
(
long
)
(
nThreads
*
writes
));
}
finally
{
file
.
delete
();
}
}
//--------------------- Infrastructure ---------------------------
volatile
int
passed
=
0
,
failed
=
0
;
void
pass
()
{
passed
++;}
void
fail
()
{
failed
++;
Thread
.
dumpStack
();}
void
fail
(
String
msg
)
{
System
.
err
.
println
(
msg
);
fail
();}
void
unexpected
(
Throwable
t
)
{
failed
++;
t
.
printStackTrace
();}
void
check
(
boolean
cond
)
{
if
(
cond
)
pass
();
else
fail
();}
void
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
null
?
y
==
null
:
x
.
equals
(
y
))
pass
();
else
fail
(
x
+
" not equal to "
+
y
);}
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
new
AtomicAppend
().
instanceMain
(
args
);}
void
instanceMain
(
String
[]
args
)
throws
Throwable
{
try
{
test
(
args
);}
catch
(
Throwable
t
)
{
unexpected
(
t
);}
System
.
out
.
printf
(
"%nPassed = %d, failed = %d%n%n"
,
passed
,
failed
);
if
(
failed
>
0
)
throw
new
AssertionError
(
"Some tests failed"
);}
}
test/java/lang/ProcessBuilder/Basic.java
浏览文件 @
73d65ed1
...
@@ -25,12 +25,15 @@
...
@@ -25,12 +25,15 @@
* @test
* @test
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031
* 6464154 6523983 6206031
4960438 6631352 6631966
* @summary Basic tests for Process and Environment Variable code
* @summary Basic tests for Process and Environment Variable code
* @run main/othervm Basic
* @run main/othervm Basic
* @author Martin Buchholz
* @author Martin Buchholz
*/
*/
import
java.lang.ProcessBuilder.Redirect
;
import
static
java
.
lang
.
ProcessBuilder
.
Redirect
.*;
import
java.io.*
;
import
java.io.*
;
import
java.util.*
;
import
java.util.*
;
import
java.security.*
;
import
java.security.*
;
...
@@ -257,7 +260,29 @@ public class Basic {
...
@@ -257,7 +260,29 @@ public class Basic {
public
static
class
JavaChild
{
public
static
class
JavaChild
{
public
static
void
main
(
String
args
[])
throws
Throwable
{
public
static
void
main
(
String
args
[])
throws
Throwable
{
String
action
=
args
[
0
];
String
action
=
args
[
0
];
if
(
action
.
equals
(
"System.getenv(String)"
))
{
if
(
action
.
equals
(
"testIO"
))
{
String
expected
=
"standard input"
;
char
[]
buf
=
new
char
[
expected
.
length
()+
1
];
int
n
=
new
InputStreamReader
(
System
.
in
).
read
(
buf
,
0
,
buf
.
length
);
if
(
n
!=
expected
.
length
())
System
.
exit
(
5
);
if
(!
new
String
(
buf
,
0
,
n
).
equals
(
expected
))
System
.
exit
(
5
);
System
.
err
.
print
(
"standard error"
);
System
.
out
.
print
(
"standard output"
);
}
else
if
(
action
.
equals
(
"testInheritIO"
))
{
List
<
String
>
childArgs
=
new
ArrayList
<
String
>(
javaChildArgs
);
childArgs
.
add
(
"testIO"
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
childArgs
);
pb
.
inheritIO
();
ProcessResults
r
=
run
(
pb
);
if
(!
r
.
out
().
equals
(
""
))
System
.
exit
(
7
);
if
(!
r
.
err
().
equals
(
""
))
System
.
exit
(
8
);
if
(
r
.
exitValue
()
!=
0
)
System
.
exit
(
9
);
}
else
if
(
action
.
equals
(
"System.getenv(String)"
))
{
String
val
=
System
.
getenv
(
args
[
1
]);
String
val
=
System
.
getenv
(
args
[
1
]);
printUTF8
(
val
==
null
?
"null"
:
val
);
printUTF8
(
val
==
null
?
"null"
:
val
);
}
else
if
(
action
.
equals
(
"System.getenv(\\u1234)"
))
{
}
else
if
(
action
.
equals
(
"System.getenv(\\u1234)"
))
{
...
@@ -599,6 +624,333 @@ public class Basic {
...
@@ -599,6 +624,333 @@ public class Basic {
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
}
static
void
checkRedirects
(
ProcessBuilder
pb
,
Redirect
in
,
Redirect
out
,
Redirect
err
)
{
equal
(
pb
.
redirectInput
(),
in
);
equal
(
pb
.
redirectOutput
(),
out
);
equal
(
pb
.
redirectError
(),
err
);
}
static
void
redirectIO
(
ProcessBuilder
pb
,
Redirect
in
,
Redirect
out
,
Redirect
err
)
{
pb
.
redirectInput
(
in
);
pb
.
redirectOutput
(
out
);
pb
.
redirectError
(
err
);
}
static
void
setFileContents
(
File
file
,
String
contents
)
{
try
{
Writer
w
=
new
FileWriter
(
file
);
w
.
write
(
contents
);
w
.
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
static
String
fileContents
(
File
file
)
{
try
{
Reader
r
=
new
FileReader
(
file
);
StringBuilder
sb
=
new
StringBuilder
();
char
[]
buffer
=
new
char
[
1024
];
int
n
;
while
((
n
=
r
.
read
(
buffer
))
!=
-
1
)
sb
.
append
(
buffer
,
0
,
n
);
r
.
close
();
return
new
String
(
sb
);
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
return
""
;
}
}
static
void
testIORedirection
()
throws
Throwable
{
final
File
ifile
=
new
File
(
"ifile"
);
final
File
ofile
=
new
File
(
"ofile"
);
final
File
efile
=
new
File
(
"efile"
);
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
//----------------------------------------------------------------
// Check mutual inequality of different types of Redirect
//----------------------------------------------------------------
Redirect
[]
redirects
=
{
PIPE
,
INHERIT
,
Redirect
.
from
(
ifile
),
Redirect
.
to
(
ifile
),
Redirect
.
appendTo
(
ifile
),
Redirect
.
from
(
ofile
),
Redirect
.
to
(
ofile
),
Redirect
.
appendTo
(
ofile
),
};
for
(
int
i
=
0
;
i
<
redirects
.
length
;
i
++)
for
(
int
j
=
0
;
j
<
redirects
.
length
;
j
++)
equal
(
redirects
[
i
].
equals
(
redirects
[
j
]),
(
i
==
j
));
//----------------------------------------------------------------
// Check basic properties of different types of Redirect
//----------------------------------------------------------------
equal
(
PIPE
.
type
(),
Redirect
.
Type
.
PIPE
);
equal
(
PIPE
.
toString
(),
"PIPE"
);
equal
(
PIPE
.
file
(),
null
);
equal
(
INHERIT
.
type
(),
Redirect
.
Type
.
INHERIT
);
equal
(
INHERIT
.
toString
(),
"INHERIT"
);
equal
(
INHERIT
.
file
(),
null
);
equal
(
Redirect
.
from
(
ifile
).
type
(),
Redirect
.
Type
.
READ
);
equal
(
Redirect
.
from
(
ifile
).
toString
(),
"redirect to read from file \"ifile\""
);
equal
(
Redirect
.
from
(
ifile
).
file
(),
ifile
);
equal
(
Redirect
.
from
(
ifile
),
Redirect
.
from
(
ifile
));
equal
(
Redirect
.
from
(
ifile
).
hashCode
(),
Redirect
.
from
(
ifile
).
hashCode
());
equal
(
Redirect
.
to
(
ofile
).
type
(),
Redirect
.
Type
.
WRITE
);
equal
(
Redirect
.
to
(
ofile
).
toString
(),
"redirect to write to file \"ofile\""
);
equal
(
Redirect
.
to
(
ofile
).
file
(),
ofile
);
equal
(
Redirect
.
to
(
ofile
),
Redirect
.
to
(
ofile
));
equal
(
Redirect
.
to
(
ofile
).
hashCode
(),
Redirect
.
to
(
ofile
).
hashCode
());
equal
(
Redirect
.
appendTo
(
ofile
).
type
(),
Redirect
.
Type
.
APPEND
);
equal
(
Redirect
.
appendTo
(
efile
).
toString
(),
"redirect to append to file \"efile\""
);
equal
(
Redirect
.
appendTo
(
efile
).
file
(),
efile
);
equal
(
Redirect
.
appendTo
(
efile
),
Redirect
.
appendTo
(
efile
));
equal
(
Redirect
.
appendTo
(
efile
).
hashCode
(),
Redirect
.
appendTo
(
efile
).
hashCode
());
//----------------------------------------------------------------
// Check initial values of redirects
//----------------------------------------------------------------
List
<
String
>
childArgs
=
new
ArrayList
<
String
>(
javaChildArgs
);
childArgs
.
add
(
"testIO"
);
final
ProcessBuilder
pb
=
new
ProcessBuilder
(
childArgs
);
checkRedirects
(
pb
,
PIPE
,
PIPE
,
PIPE
);
//----------------------------------------------------------------
// Check inheritIO
//----------------------------------------------------------------
pb
.
inheritIO
();
checkRedirects
(
pb
,
INHERIT
,
INHERIT
,
INHERIT
);
//----------------------------------------------------------------
// Check setters and getters agree
//----------------------------------------------------------------
pb
.
redirectInput
(
ifile
);
equal
(
pb
.
redirectInput
().
file
(),
ifile
);
equal
(
pb
.
redirectInput
(),
Redirect
.
from
(
ifile
));
pb
.
redirectOutput
(
ofile
);
equal
(
pb
.
redirectOutput
().
file
(),
ofile
);
equal
(
pb
.
redirectOutput
(),
Redirect
.
to
(
ofile
));
pb
.
redirectError
(
efile
);
equal
(
pb
.
redirectError
().
file
(),
efile
);
equal
(
pb
.
redirectError
(),
Redirect
.
to
(
efile
));
THROWS
(
IllegalArgumentException
.
class
,
new
Fun
(){
void
f
()
{
pb
.
redirectInput
(
Redirect
.
to
(
ofile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectInput
(
Redirect
.
appendTo
(
ofile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectOutput
(
Redirect
.
from
(
ifile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectError
(
Redirect
.
from
(
ifile
));
}});
THROWS
(
IOException
.
class
,
// Input file does not exist
new
Fun
(){
void
f
()
throws
Throwable
{
pb
.
start
();
}});
setFileContents
(
ifile
,
"standard input"
);
//----------------------------------------------------------------
// Writing to non-existent files
//----------------------------------------------------------------
{
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Both redirectErrorStream + redirectError
//----------------------------------------------------------------
{
pb
.
redirectErrorStream
(
true
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard error"
+
"standard output"
);
equal
(
fileContents
(
efile
),
""
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Appending to existing files
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
pb
.
redirectOutput
(
Redirect
.
appendTo
(
ofile
));
pb
.
redirectError
(
Redirect
.
appendTo
(
efile
));
pb
.
redirectErrorStream
(
false
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"ofile-contents"
+
"standard output"
);
equal
(
fileContents
(
efile
),
"efile-contents"
+
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Replacing existing files
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
pb
.
redirectOutput
(
ofile
);
pb
.
redirectError
(
Redirect
.
to
(
efile
));
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Appending twice to the same file?
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
Redirect
appender
=
Redirect
.
appendTo
(
ofile
);
pb
.
redirectOutput
(
appender
);
pb
.
redirectError
(
appender
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"ofile-contents"
+
"standard error"
+
"standard output"
);
equal
(
fileContents
(
efile
),
"efile-contents"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Testing INHERIT is harder.
// Note that this requires __FOUR__ nested JVMs involved in one test,
// if you count the harness JVM.
//----------------------------------------------------------------
{
redirectIO
(
pb
,
PIPE
,
PIPE
,
PIPE
);
List
<
String
>
command
=
pb
.
command
();
command
.
set
(
command
.
size
()
-
1
,
"testInheritIO"
);
Process
p
=
pb
.
start
();
new
PrintStream
(
p
.
getOutputStream
()).
print
(
"standard input"
);
p
.
getOutputStream
().
close
();
ProcessResults
r
=
run
(
p
);
equal
(
r
.
exitValue
(),
0
);
equal
(
r
.
out
(),
"standard output"
);
equal
(
r
.
err
(),
"standard error"
);
}
//----------------------------------------------------------------
// Test security implications of I/O redirection
//----------------------------------------------------------------
// Read access to current directory is always granted;
// So create a tmpfile for input instead.
final
File
tmpFile
=
File
.
createTempFile
(
"Basic"
,
"tmp"
);
setFileContents
(
tmpFile
,
"standard input"
);
final
Policy
policy
=
new
Policy
();
Policy
.
setPolicy
(
policy
);
System
.
setSecurityManager
(
new
SecurityManager
());
try
{
final
Permission
xPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"execute"
);
final
Permission
rxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"read,execute"
);
final
Permission
wxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"write,execute"
);
final
Permission
rwxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"read,write,execute"
);
THROWS
(
SecurityException
.
class
,
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
xPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
PIPE
,
PIPE
);
pb
.
start
();}},
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
PIPE
,
to
(
ofile
),
PIPE
);
pb
.
start
();}},
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
PIPE
,
PIPE
,
to
(
efile
));
pb
.
start
();}});
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
PIPE
,
PIPE
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
out
(),
"standard output"
);
equal
(
r
.
err
(),
"standard error"
);
}
{
policy
.
setPermissions
(
wxPermission
);
redirectIO
(
pb
,
PIPE
,
to
(
ofile
),
to
(
efile
));
Process
p
=
pb
.
start
();
new
PrintStream
(
p
.
getOutputStream
()).
print
(
"standard input"
);
p
.
getOutputStream
().
close
();
ProcessResults
r
=
run
(
p
);
policy
.
setPermissions
(
rwxPermission
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
}
{
policy
.
setPermissions
(
rwxPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
to
(
ofile
),
to
(
efile
));
ProcessResults
r
=
run
(
pb
);
policy
.
setPermissions
(
rwxPermission
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
}
}
finally
{
policy
.
setPermissions
(
new
RuntimePermission
(
"setSecurityManager"
));
System
.
setSecurityManager
(
null
);
tmpFile
.
delete
();
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
}
}
private
static
void
realMain
(
String
[]
args
)
throws
Throwable
{
private
static
void
realMain
(
String
[]
args
)
throws
Throwable
{
if
(
Windows
.
is
())
if
(
Windows
.
is
())
System
.
out
.
println
(
"This appears to be a Windows system."
);
System
.
out
.
println
(
"This appears to be a Windows system."
);
...
@@ -607,6 +959,9 @@ public class Basic {
...
@@ -607,6 +959,9 @@ public class Basic {
if
(
UnicodeOS
.
is
())
if
(
UnicodeOS
.
is
())
System
.
out
.
println
(
"This appears to be a Unicode-based OS."
);
System
.
out
.
println
(
"This appears to be a Unicode-based OS."
);
try
{
testIORedirection
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
//----------------------------------------------------------------
//----------------------------------------------------------------
// Basic tests for setting, replacing and deleting envvars
// Basic tests for setting, replacing and deleting envvars
//----------------------------------------------------------------
//----------------------------------------------------------------
...
@@ -1354,7 +1709,8 @@ public class Basic {
...
@@ -1354,7 +1709,8 @@ public class Basic {
execPermission
);
execPermission
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
"env"
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
"env"
);
pb
.
environment
().
put
(
"foo"
,
"bar"
);
pb
.
environment
().
put
(
"foo"
,
"bar"
);
pb
.
start
();
Process
p
=
pb
.
start
();
closeStreams
(
p
);
}
catch
(
IOException
e
)
{
// OK
}
catch
(
IOException
e
)
{
// OK
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
...
@@ -1378,6 +1734,14 @@ public class Basic {
...
@@ -1378,6 +1734,14 @@ public class Basic {
}
}
static
void
closeStreams
(
Process
p
)
{
try
{
p
.
getOutputStream
().
close
();
p
.
getInputStream
().
close
();
p
.
getErrorStream
().
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
//----------------------------------------------------------------
//----------------------------------------------------------------
// A Policy class designed to make permissions fiddling very easy.
// A Policy class designed to make permissions fiddling very easy.
//----------------------------------------------------------------
//----------------------------------------------------------------
...
@@ -1432,10 +1796,19 @@ public class Basic {
...
@@ -1432,10 +1796,19 @@ public class Basic {
}
}
}
catch
(
Throwable
t
)
{
}
catch
(
Throwable
t
)
{
throwable
=
t
;
throwable
=
t
;
}
finally
{
try
{
is
.
close
();
}
catch
(
Throwable
t
)
{
throwable
=
t
;
}
}
}
}
}
}
}
static
ProcessResults
run
(
ProcessBuilder
pb
)
{
try
{
return
run
(
pb
.
start
());
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
return
null
;
}
}
private
static
ProcessResults
run
(
Process
p
)
{
private
static
ProcessResults
run
(
Process
p
)
{
Throwable
throwable
=
null
;
Throwable
throwable
=
null
;
int
exitValue
=
-
1
;
int
exitValue
=
-
1
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录