8373647: Avoid fstat when opening file for write with RandomAccessFile or FileOutputStream

Reviewed-by: redestad, alanb
This commit is contained in:
Jonas Norlinder 2026-01-08 16:46:28 +00:00 committed by Claes Redestad
parent fa2eb62647
commit c834e4c641
2 changed files with 46 additions and 13 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2025, 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
@ -27,6 +27,7 @@
#include "jvm.h"
#include "io_util.h"
#include "io_util_md.h"
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
@ -75,20 +76,26 @@ FD
handleOpen(const char *path, int oflag, int mode) {
FD fd;
RESTARTABLE(open(path, oflag, mode), fd);
if (fd != -1) {
struct stat buf;
int result;
RESTARTABLE(fstat(fd, &buf), result);
if (result != -1) {
if (S_ISDIR(buf.st_mode)) {
close(fd);
errno = EISDIR;
fd = -1;
}
} else {
// No further checking is needed if the file is not a
// directory or open returned an error
if (fd == -1 || ((oflag & O_ACCMODE) != O_RDONLY) != 0) {
return fd;
}
// FileInputStream is specified to throw if the
// file is a directory
struct stat buf;
int result;
RESTARTABLE(fstat(fd, &buf), result);
if (result != -1) {
if (S_ISDIR(buf.st_mode)) {
close(fd);
errno = EISDIR;
fd = -1;
}
} else {
close(fd);
fd = -1;
}
return fd;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, 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
@ -25,6 +25,7 @@ package org.openjdk.bench.java.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@ -81,4 +82,29 @@ public class FileWrite {
}
}
@State(Scope.Benchmark)
@Warmup(iterations = 3, time = 2)
@Measurement(iterations = 5, time = 5)
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Threads(1)
@Fork(value = 10)
public static class OpenFileForWritingBench {
final byte[] payload = "something".getBytes();
final String path = System.getProperty("os.name", "unknown").toLowerCase().contains("win") ? "NUL" : "/dev/null";
@Benchmark
public void testFileOutputStream() throws IOException {
try (FileOutputStream f = new FileOutputStream(path)) {
f.write(payload);
}
}
@Benchmark
public void testRandomAccessFile() throws IOException {
try (RandomAccessFile f = new RandomAccessFile(path, "rw")) {
f.write(payload);
}
}
}
}