关于java io 的 write 与 操作系统

8 篇文章 0 订阅
3 篇文章 0 订阅

新文章连接

熟悉linux 的同学 对 sync、fsync与fdatasync 应该不会陌生
如果不熟悉可以看下这篇总结不错的文章http://www.cnblogs.com/bhlsheji/p/5222271.html

但是java和其关系如何呢?
先上个栗子

@Test
    public void file(){

        try (FileOutputStream fo = new FileOutputStream("D:\\temp\\file",true)) {

            for(int i=0;i<17;i++){
                fo.write(String.format("Line : %s \n",i).getBytes());
                fo.flush();
                if(i%3==0){
                    fo.getFD().sync();
                }
                TimeUnit.MILLISECONDS.sleep(1000);
                System.out.println(i);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

一般来说我们会用flush,但是在需要确保数据落盘的场景,我们如何保证呢?java的实现是哪个级别的sync?

FileDescriptor 内的sync声明如下

public native void sync() throws SyncFailedException;

然后参阅openjdk的实现
openjdk/jdk/src/java.base/unix/native/libjava/FileDescriptor_md.c

JNIEXPORT void JNICALL
Java_java_io_FileDescriptor_sync(JNIEnv *env, jobject this) {
    FD fd = THIS_FD(this);
    if (IO_Sync(fd) == -1) {
        JNU_ThrowByName(env, "java/io/SyncFailedException", "sync failed");
    }
}

可以看到jvm直接调用了IO_Sync方法,而该方法的定义位于
openjdk/jdk/src/java.base/unix/native/libjava/io_util_md.h

/*
 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "jni_util.h"

/*
 * Macros to use the right data type for file descriptors
 */
#define FD jint

/*
 * Prototypes for functions in io_util_md.c called from io_util.c,
 * FileDescriptor.c, FileInputStream.c, FileOutputStream.c,
 * UnixFileSystem_md.c
 */
ssize_t handleWrite(FD fd, const void *buf, jint len);
ssize_t handleRead(FD fd, void *buf, jint len);
jint handleAvailable(FD fd, jlong *pbytes);
jint handleSetLength(FD fd, jlong length);
jlong handleGetLength(FD fd);
FD handleOpen(const char *path, int oflag, int mode);

/*
 * Macros to set/get fd from the java.io.FileDescriptor.  These
 * macros rely on having an appropriately defined 'this' object
 * within the scope in which they're used.
 * If GetObjectField returns null, SET_FD will stop and GET_FD
 * will simply return -1 to avoid crashing VM.
 */

#define SET_FD(this, fd, fid) \
    if ((*env)->GetObjectField(env, (this), (fid)) != NULL) \
        (*env)->SetIntField(env, (*env)->GetObjectField(env, (this), (fid)),IO_fd_fdID, (fd))

#define GET_FD(this, fid) \
    (*env)->GetObjectField(env, (this), (fid)) == NULL ? \
        -1 : (*env)->GetIntField(env, (*env)->GetObjectField(env, (this), (fid)), IO_fd_fdID) /* * Macros to set/get fd when inside java.io.FileDescriptor */ #define THIS_FD(obj) (*env)->GetIntField(env, obj, IO_fd_fdID) /* * Route the routines */ #define IO_Sync fsync #define IO_Read handleRead #define IO_Write handleWrite #define IO_Append handleWrite #define IO_Available handleAvailable #define IO_SetLength handleSetLength #define IO_GetLength handleGetLength #ifdef _ALLBSD_SOURCE #define open64 open #define fstat64 fstat #define stat64 stat #define lseek64 lseek #define ftruncate64 ftruncate #define IO_Lseek lseek #else #define IO_Lseek lseek64 #endif /* * On Solaris, the handle field is unused */ #define SET_HANDLE(fd) return (jlong)-1 /* * Retry the operation if it is interrupted */ #define RESTARTABLE(_cmd, _result) do { \ do { \ _result = _cmd; \ } while((_result == -1) && (errno == EINTR)); \ } while(0) /* * IO helper function(s) */ void fileClose(JNIEnv *env, jobject this, jfieldID fid); #ifdef MACOSX jstring newStringPlatform(JNIEnv *env, const char* str); #endif

所以,fo.getFD().sync()方法本质上调用了系统的fsync方法。这个层面,java和c可以做到同样的控制粒度了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值