欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

Too many open files); retu CAD加密 rn -1; } throwFileNotFound

点击: 次  来源:宝鼎软件 时间:2017-07-29

原文出处: 左潇龙

设计模式系列竣事,迎来了LZ第一篇关于JAVA虚拟机的文章,这一系列文章不再像之前的设计模式一样,有着严格的约束力,本系列文章相对会较量随性,本次LZ就跟列位分享一个关于FileInputStream的小奥秘。

在探究这个奥秘之前,列位假如没有openjdk的源码,可以去LZ的资源先下载下来,链接是:JVM源码 和 JDK源码。

由于资源有最大60MB的限制,所以LZ分成了两部门,一个是JVM的源码,一个是JDK中的源码,而当处所法的源码都在JDK的谁人压缩包傍边,全部源码下载在openjdk的官网上也有,列位也可以去哪里找一下,假如嫌贫苦的话,就去LZ的资源里下载即可。

此刻源码我们已经有了,可以来看下我们研究的小奥秘了。各人都知道我们在读取文件时离不开FileInputStream这个类,那么不知道列位有没有好奇过,我们的FileInputStream是如何成立的呢?

我们一起先来看看FileInputStream的源码,我们平时都是通过new FileInputStream(name or File)的方法获得的文件输入流,所以我们来看FileInputStream的结构要领。

public
class FileInputStream extends InputStream
{
    /* File Descriptor - handle to the open file */
    private FileDescriptor fd;

    private FileChannel channel = null;

    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }
    //这个要领是我们建设文件输入流时的方法
    public FileInputStream(File file) throws FileNotFoundException {
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(name);
    }
        if (name == null) {
            throw new NullPointerException();
        }
    fd = new FileDescriptor();
    open(name);
    }

我们忽略安详打点器的查抄,可以看到,在建设一个文件输入流时,主要做了两件事,一个是new一个FileDescriptor(文件描写符),一个即是挪用了open要领。

不外在此之前,其实还挪用了一个要领,在FileInputStream源码的下方,有这样一个静态块。

static {
       initIDs();
    }

它将在第一次加载FileInputStream类的时候,挪用一个静态的initIDs的当处所法,这里我们不跟踪这个要领的源码,它并不是我们的重点,它的浸染是配置类中(也就是FileInputStream)的属性的地点偏移量,便于在须要时操纵内存给它赋值,而FileInputStream的initIDs要领只配置了fd这一个属性的地点偏移量。

接下来,我们首先看下FileDescriptor这个类是什么样子的,它的源码如下。

package java.io;

public final class FileDescriptor {

    private int fd;

    private long handle;

    /**
     * Constructs an (invalid) FileDescriptor
     * object.
     */
    public /**/ FileDescriptor() {
    fd = -1;
        handle = -1;
    }

    private /* */ FileDescriptor(int fd) {
    this.fd = fd;
        handle = -1;
    }

    static {
        initIDs();
    }

    /**
     * A handle to the standard input stream. Usually, this file
     * descriptor is not used directly, but rather via the input stream
     * known as <code>System.in</code>.
     *
     * @see     java.lang.System#in
     */
    public static final FileDescriptor in = standardStream(0);

    /**
     * A handle to the standard output stream. Usually, this file
     * descriptor is not used directly, but rather via the output stream
     * known as <code>System.out</code>.
     * @see     java.lang.System#out
     */
    public static final FileDescriptor out = standardStream(1);

    /**
     * A handle to the standard error stream. Usually, this file
     * descriptor is not used directly, but rather via the output stream
     * known as <code>System.err</code>.
     *
     * @see     java.lang.System#err
     */
    public static final FileDescriptor err = standardStream(2);

    /**
     * Tests if this file descriptor object is valid.
     *
     * @return  <code>true</code> if the file descriptor object represents a
     *          valid, open file, socket, or other active I/O connection;
     *          <code>false</code> otherwise.
     */
    public boolean valid() {
    return ((handle != -1) || (fd != -1));
    }

    public native void sync() throws SyncFailedException;

    /* This routine initializes JNI field offsets for the class */
    private static native void initIDs();

    private static native long set(int d);

    private static FileDescriptor standardStream(int fd) {
        FileDescriptor desc = new FileDescriptor();
        desc.handle = set(fd);
        return desc;
    }

}

可以看到,这内里也有initIDs的静态块,它与FileInputStream中的静态块的浸染雷同,只不外这里配置了两个属性(fd和handle)的地点偏移量。