不要在linux上使用java 7 Files的接口参数StandardOpenOption.DELETE_ON_CLOSE

最近在看安全代码规范建议中提到关于如何删除创建的临时文件,推荐使用jdk7中的Files的函数,通过参数StandardOpenOption.DELETE_ON_CLOSE来控制

代码示例

BufferedWriter writer = Files.newBufferedWriter(tempFile, Charset.forName("UTF8"), StandardOpenOption.DELETE_ON_CLOSE)

只要当文件close掉,这个文件就会自动被系统删除,这样可以避免在一些场景下忘了删除产生的临时文件。

StandardOpenOption.DELETE_ON_CLOSE参数

我们来看代码StandardOpenOption.DELETE_ON_CLOSE参数在linux下究竟控制了什么,我们在java代码中看到了参数的控制阀

if (flags.deleteOnClose) {
            try {
                if (dfd >= 0) {
                    unlinkat(dfd, path.asByteArray(), 0);
                } else {
                    unlink(path);
                }
            } catch (UnixException ignore) {
                // best-effort
            }
        }

java的unlink函数

static void unlink(UnixPath path) throws UnixException {
        NativeBuffer buffer = copyToNativeBuffer(path);
        try {
            unlink0(buffer.address());
        } finally {
            buffer.release();
        }
    }

JNI unlink0函数

JNIEXPORT void JNICALL
Java_sun_nio_fs_UnixNativeDispatcher_unlink0(JNIEnv* env, jclass this,
    jlong pathAddress)
{
    const char* path = (const char*)jlong_to_ptr(pathAddress);

    /* EINTR not listed as a possible error */
    if (unlink(path) == -1) {
        throwUnixException(env, errno);
    }
}

最后调用了系统unlink函数

unlink rm unlinkat remove的区别

我们通常会使用shell rm去删除文件,让我们先看看rm做了什么,通过strace来查看系统调用strace rm filepath会看到最后调用的函数unlinkat

unlink 和 unlinkat 的区别

unlinkat 可以通过参数AT_REMOVEDIR删除空的目录,其他的是和unlink一样

unlinkat(AT_FDCWD, "/tmp/test", AT_REMOVEDIR) 

remove 和 unlink的区别

remove是unlink 和 rmdir 合集,区别也是在删除目录上

可以看到说参数StandardOpenOption.DELETE_ON_CLOSE 在linux上是调用了unlink删除了文件名,那么也就意味着你对这个文件的任何读写操作都是无效的。

Linux和windows的区别

参数StandardOpenOption.DELETE_ON_CLOSE在Linux和windows是不一样的实现,windows上只有调用了writer.close() 这个文件才会被删除,也就是windows上的open函数本身就带有文件属性FILE_FLAG_DELETE_ON_CLOSE,当显式的调用close,自然就会删除该文件,而如果进程退出也会删除这个文件。

总结:

参数StandardOpenOption.DELETE_ON_CLOSE对Linux 来说是无效的操作,虽然保证了文件的删除,但也违反了本身API的协议(需要调用close才能真实的删除文件)。

而且本身也没有实际意义,因为文件已经被删除了,那就意味着本身也无法向文件中写任何内容,那么创建临时文件的意义也不存在了。这个函数在windows上是实现的,而Linux中没有类似的内核函数去实现这样的功能。

File函数的方法deleteOnExit

File.deleteOnExit()

这个方法在jvm退出时添加了一个钩子,退出时删除文件。但是如果jvm没有正常退出呢?比如我们常用的信号退出,就没有办法正常删除文件。

StandardOpenOption.DELETE_ON_CLOSE这是需要在内核函数中去实现这个属性,而不是在jvm 应用层去实现,而jvm 在针对Linux 直接调用unlink 也是避免了问题的复杂化。

时间: 2024-10-23 03:54:55

不要在linux上使用java 7 Files的接口参数StandardOpenOption.DELETE_ON_CLOSE的相关文章

在linux上部署Java项目

在linux上部署Java项目 查看tomcat的运行状态 ps -auxwf | grep java 或者查看 端口的占用,具体端口看自己的配置 netstat -lnpt | grep 8080 启动和关闭 打开 ./startup.sh 关闭 ./shutdown.sh 查看MySql的运行状态 /etc/init.d/mysqld status #已添加到系统服务,以下命令可以查看 service mysqld status 或者过滤进程名或者端口(参考自己的设置) ps -aux |

Linux上部署Java项目

一.在Linux上安装jdk 下载:登录网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 选择对应jdk版本下载.(可在Windows上下载完成后,通过ftp文件夹共享到Linux上) 登陆linux:su root 获取root用户权限,当前工作目录不变(需要root密码)或sudo -i 不需要root密码直接切换成root(需要当前用户密码) 在user目录下建立ja

在Linux上使用Java

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权:凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记. Linux与Windows的操作区别 Windows的操作首先是通过图形化界面然后通过后台生成命令给操作系统 Linux的是直接操作命令给操作系统 Windows的结构是>>盘符>>夹子 Linux的结构是>>夹子 Linux的下载及安装 1.首先从将VM程序安装好 然后在网上下载好centOS7的镜像文件 2.在vm中创建一个新的

Linux上从Java程序中调用C函数

原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Java代码比其他语言编写的等价代码慢得多: 其他语言编写的代码已经经过大量测试和调试,并且知道如何将其导出到所有的目标平台上. Java平台有一个用于和本地C.C++代码进行互操作的API,称为Java本地接口(JNI).下面将举例讨论Linux平台下的JNI编程. 1. 创建java类文件 创建一个native

Linux上安装java

下载: http://java.sun.com/javase/downloads 选择Linux 64位 .tar.gz 文件 解压.移动: tar -xzvf /root/jdk-7u45-linux-x64.tar.gz mv jdk1.7.0_45 /opt cd /opt/jdk1.7.0_4 注册: update-alternatives --install /usr/bin/java java /opt/jdk1.7.0_45/bin/java 1 update-alternativ

Linux上部署Java应用

给了Linux的测试环境,目前需要install JDK, Tomcat,此处记录下小白的操作过程. 1. 查询Linux发行版本,包括内核信息 (1) Linux查询内核信息 $ uname -a Linux ECA-LPH000007 3.10.0-514.6.1.el7.x86_64 #1 SMP Wed Jan 18 13:06:36 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux $ cat /proc/version Linux version 3.1

Linux上分析java程序的问题

通过日志看不出来的问题,可以通过看java的堆栈信息(dump文件)来看出一些端倪. 1. 找java的进程id.jdk/bin的目录 ps -ef | grep java 2. cd 到bin的目录,执行jstack命令 ./jstack [pid]    需要在catalina_yyyy-MM-dd.log里面看dump信息 ./jstack -l -F [pid]  强制打印栈信息,可以在console中看dump信息 参数: -F   当’jstack [-l] pid’没有相应的时候强

在Linux上讲Java命令行的作为服务运行

现在Spring等框架可以支持别用War发布而是用Jar发布,这样服务器就不用安装容器了,方便不少.但不安装容器就需要自己来写脚本完成服务的启动.停止.重启. 脚本如下: #!/bin/bash # # chkconfig: 345 70 30 # description: ${description} # processname: ${processName} # Source function library. #!/bin/sh SERVICE_NAME=${serviceName} PA

Linux上安装java JDK

yum方式 1.查看yum中的各个版本 yum -y list java* 2.选择一个版本安装(如1.7) yum -y install java-1.7.0-openjdk* 3.安装完成后可查看版本信息 java -version  //如果会打印版本信息说明安装成功,yum安装会自动设置环境变量,无需手动设置 rpm方式 1.去http://www.oracle.com/technetwork/java/javase/downloads/index.html下载java JDK 的rpm