如何通过Java 真正使用块设备刷新/同步写入文件的数据.
我用NIO试过这段代码:
FileOutputStream s = new FileOutputStream(filename)
Channel c = s.getChannel()
while(xyz)
c.write(buffer)
c.force(true)
s.getFD().sync()
c.close()
Run Code Online (Sandbox Code Playgroud)
我认为c.force(true)与s.getFD()同步.sync()应该足够了,因为强制状态的文档
强制将此通道文件的任何更新写入包含它的存储设备.如果此通道的文件驻留在本地存储设备上,则当此方法返回时,保证自创建此通道以来对文件所做的所有更改,或者自上次调用此方法以来,该文件都将写入该设备.这对于确保在系统崩溃时不会丢失关键信息非常有用.
同步状态的文档:
强制所有系统缓冲区与底层设备同步.在将此FileDescriptor的所有已修改数据和属性写入相关设备之后,此方法返回.特别是,如果此FileDescriptor引用物理存储介质(例如文件系统中的文件),则在将与此FileDesecriptor关联的缓冲区的所有内存中修改副本写入物理介质之前,不会返回sync.sync意味着需要物理存储(例如文件)处于已知状态的代码.
这两个电话应该足够了.是吗?我猜他们不是.
背景:我使用C/Java进行小的性能比较(2 GB,顺序写入),Java版本的速度是C版本的两倍,可能比硬件速度快(单个HD上的速度为120 MB/s).我还尝试使用Runtime.getRuntime().exec("sync")执行命令行工具同步,但这并没有改变行为.
导致70 MB/s的C代码(使用低级API(打开,写入,关闭)不会发生太大变化):
FILE* fp = fopen(filename, "w");
while(xyz) {
fwrite(buffer, 1, BLOCK_SIZE, fp);
}
fflush(fp);
fclose(fp);
sync();
Run Code Online (Sandbox Code Playgroud)
没有最后的同步调用; 我得到了不切实际的价值(超过1 GB又称主内存性能).
为什么C和Java之间有这么大的差异?有两种可能性:我没有在Java中正确地同步数据,或者C代码由于某种原因是次优的.
更新:我已经使用"strace -cfT cmd"完成了strace运行.结果如下:
C(低级API):MB/s 67.389782
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 87.21 0.200012 200012 1 fdatasync 11.05 0.025345 1 32772 write 1.74 0.004000 …
在某些情况下,我需要立即强制刷新logback的文件appender.我在docs中发现默认情况下启用此选项.神秘地说这不起作用.正如我在源代码中看到的过程涉及BufferedOutputSream正确.有什么问题BufferedOutputSream.flush()吗?可能这与冲洗问题有关.
更新:我在Windows XP Pro SP 3和Red Hat Enterprise Linux Server 5.3版(Tikanga)上发现了这个问题.我使用了这些库:
jcl-over-slf4j-1.6.6.jar
logback-classic-1.0.6.jar
logback-core-1.0.6.jar
slf4j-api-1.6.6.jar
Run Code Online (Sandbox Code Playgroud)
该logback.xml方法是:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/somepath/file.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>file.log.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
Run Code Online (Sandbox Code Playgroud)
更新: 我提供单元测试,但似乎不那么简单.让我更清楚地描述这个问题.
immidiateFlush默认情况下为true,因此flush()显式调用方法稍后当一些底层缓冲区流动时,事件出现在文件中.所以问题是:输出流是否保证立即刷新?
说实话,我已经通过实现我自己的ImmediateRollingFileAppender利用FileDescriptor立即同步的工具来解决这个问题.任何有兴趣的人都可以这样做.
所以这不是一个回归问题.
我在Windows Server 2016上有一个Java 10应用程序,它使用java.util.logging不断写入文件.在Windows文件资源管理器中,"上次修改"和"大小"列不会更新.按[F5]不会更新详细信息.DOS DIR给出了同样错误的答案.右键单击>属性>详细信息提供了一个甚至不同(和更旧)的答案.
只TYPE在文件的记事本中运行DOS 或打开/关闭(不保存),似乎导致文件资源管理器和DOS DIR更新.
我假设Java代码是正确的,flush()因为Windows Server 2008上的Java 8上的相同类导致文件资源管理器更新.另外,当运行TYPE和记事本时,我也看到与系统时钟匹配的带时间戳的记录,但在"上次修改"之后.
所以我假设Windows Server 2016有一些东西.任何想法要检查什么?
我正在努力从现有的Java代码库中删除所有系统调用.我们在商业提供的闭源JVM中运行我们的应用程序.当JVM通过getRuntime.exec()进行系统调用时,java会调用整个JVM进程分支,从而导致严重的性能命中.我们在Linux平台上运行,但最好尽量保持便携性.
我遇到的问题是通过getRuntime.exec()方法替换我们当前使用的sync()调用.我知道有这个 sync()方法和flush().基于这篇文章,我希望进行同步并刷新所有打开的文件流.
我的问题是我不知道那里有什么文件流和描述符.我认为解决这个问题的方法是检查/ proc /(jvm进程号)/ fd文件夹,但我找不到使用纯java可靠地获取JVM进程号的好方法.我以为我可以获得某个类的所有对象(FileDescriptor类)但是从我正在阅读的内容中也是不可行的.
有没有人有关于如何在纯java中复制*nix sync()调用的建议?
我无法理解SerializationJava 1.6 的基础知识.
下面是Dog包含Class的实例变量的CollarClass:
Dog.java
public class Dog implements Serializable {
private Collar collar;
public Collar getCollar() {
return collar;
}
public void setCollar(Collar collar) {
this.collar = collar;
}
}
Run Code Online (Sandbox Code Playgroud)
Collar类没有实现Serializable接口,如下所示:
Collar.java
public class Collar {
private int size;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我尝试序列化时,Dog为什么它不抛出NotSerializableException?根据合同,整个对象图应该实现,Serializable但我的Collar班级不满足.
以下是此演示的主要方法:
public static void main(String[] args) …Run Code Online (Sandbox Code Playgroud) java ×5
flush ×1
io ×1
java-10 ×1
logback ×1
logging ×1
serializable ×1
servlets ×1
storage ×1
system-calls ×1