相关疑难解决方法(0)

真的在Java中强制文件同步/刷新

如何通过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 …

java storage

36
推荐指数
3
解决办法
2万
查看次数

Logback文件appender不会立即刷新

在某些情况下,我需要立即强制刷新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)

更新: 我提供单元测试,但似乎不那么简单.让我更清楚地描述这个问题.

  1. 发生了记录事件
  2. 事件被传递到文件appender
  3. 事件使用定义的模式序列化
  4. 事件的序列化消息被传递给文件appender并且即将写出到输出流
  5. 写入流完成后,输出流被刷新(我已经检查了实现).请注意,immidiateFlush默认情况下为true,因此flush()显式调用方法
  6. 没有结果文件!

稍后当一些底层缓冲区流动时,事件出现在文件中.所以问题是:输出流是否保证立即刷新?

说实话,我已经通过实现我自己的ImmediateRollingFileAppender利用FileDescriptor立即同步的工具来解决这个问题.任何有兴趣的人都可以这样做.

所以这不是一个回归问题.

java io logging flush logback

16
推荐指数
1
解决办法
1万
查看次数

Java写入Windows Server 2016时,文件上次修改时未更新

我在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 java.util.logging java-10 windows-server-2016

7
推荐指数
1
解决办法
830
查看次数

没有系统调用的**nix sync()的Java实现

我正在努力从现有的Java代码库中删除所有系统调用.我们在商业提供的闭源JVM中运行我们的应用程序.当JVM通过getRuntime.exec()进行系统调用时,java会调用整个JVM进程分支,从而导致严重的性能命中.我们在Linux平台上运行,但最好尽量保持便携性.

我遇到的问题是通过getRuntime.exec()方法替换我们当前使用的sync()调用.我知道有这个 sync()方法和flush().基于这篇文章,我希望进行同步并刷新所有打开的文件流.

我的问题是我不知道那里有什么文件流和描述符.我认为解决这个问题的方法是检查/ proc /(jvm进程号)/ fd文件夹,但我找不到使用纯java可靠地获取JVM进程号的好方法.我以为我可以获得某个类的所有对象(FileDescriptor类)但是从我正在阅读的内容中也是不可行的.

有没有人有关于如何在纯java中复制*nix sync()调用的建议?

java system-calls

5
推荐指数
1
解决办法
407
查看次数

java中序列化的基础知识不明白

我无法理解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 serialization servlets web-applications serializable

4
推荐指数
1
解决办法
648
查看次数