在IO里面,要求每次读写完成的时候都要关闭,这样的话可以释放资源,那么下面的例子应该怎么释放呢:Properties props = new Properties();
props.load(new FileInputStream(new File(
System.getProperty("user.dir") + File.separator + "resources"
+ File.separator + "config.properties")));为了简便的原因,我直接把相应的输入流写进了操作的里面,作为了一个匿名对象,
那么这样以后还有到关闭流吗,还是系统可以自动关闭,或者是只能把输入流分解出来,如果是我特别的要求,
按照下面的操作才能释放相应的资源,就是把这段代码拆开,这里面具体是什么样子运行的,或者是我说的哪里不对吗?FileInputStream ips = new FileInputStream(new File(
System.getProperty("user.dir") + File.separator + "resources"
+ File.separator + "config.properties")); Properties props = new Properties();
props.load(ips);
ips.close();

解决方案 »

  1.   

    后面一种方式更好,会尽快释放资源。前一种方式最终也会释放资源,但什么时候释放不能确定,必须等待JVM垃圾收集的时候,回收这个对象的时候,InputFileStream.finalize()方法会被调用,该方法检查自身对象如未释放资源,则执行InputFileStream.close()
      

  2.   

    具体是这个意思吗?protected void finalize()
                     throws Throwable当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。 
    finalize 的常规协定是:当 JavaTM 虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。 Object 类的 finalize 方法执行非特殊性操作;它仅执行一些常规返回。Object 的子类可以重写此定义。 Java 编程语言不保证哪个线程将调用某个给定对象的 finalize 方法。但可以保证在调用 finalize 时,调用 finalize 的线程将不会持有任何用户可见的同步锁定。如果 finalize 方法抛出未捕获的异常,那么该异常将被忽略,并且该对象的终结操作将终止。 在启用某个对象的 finalize 方法后,将不会执行进一步操作,直到 Java 虚拟机再次确定尚未终止的任何线程无法再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被丢弃。 对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。 finalize 方法抛出的任何异常都会导致此对象的终结操作停止,但可以通过其他方法忽略它。 
    但是我不是很理解其中的意思?比如

    除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。 

      

  3.   

    但是我看这个方法,如果我没有new出对象,不是一个引用的话就不能自动回收了是吧?
      

  4.   

    try{
    执行的操作
    }finally{
    关闭
    }
    这样可以保证执行了关闭,不仅是流操作
      

  5.   

    所谓任何线程无法再通过任何方法访问此对象,通常指没有任何引用指向此对象。
    如果是在你举的第一个例子中,这个对象作为参数传入 props.load()方法,而在别处没有引用(变量)指向它,则在load()方法执行结束之后,它就变成了没有任何引用指向的对象。之后会在某个时刻被JVM垃圾回收。
      

  6.   

    Programmers have the responsibility of releasing resources. Files, Connections and threads should be released as soon as possible. And you're supposed to release resources robustly. So you're strongly suggested to locate the close code into finally block.
    FileInputStream ips = null;
    try {
        ips = ...;
        ...
    } finally {
        if (ips != null) {
            ips.close();
        }
    }
    Sometimes when you're going to deal with the data while the connection is active. It's a bad habit. I mean you should store the data in the memory and close the connection as soon as possible. Then you can handle the data. Don't let the resources wait for your process.
      

  7.   

    红色的意思大概是说,JVM在回收像I/O这类对象的时候,会保证在清除这类对象的时候,保证关闭I/O链接。用代码来表示就是io.close();先关闭,再清除
      

  8.   

    如果我用FileInputStream new出一个对象的时候,当我这个流不用的时候,会调用他本身重写父类的finalize方法,现在我是一个Properties对象,FileInputSteam值他里面的一个匿名类,这样的话,是Properties这个对象的引用不指向任何东西的时候自动回收,还是FileInputStream对象,如果是前者那么他怎么样找到内部匿名累的对象的方法,如果是后者他也没有引用,这样同样可以自动回收是吗,只要有new就可以,不需要对他有一个引用指向?
      

  9.   

    如果不是类的成员声明,那就只是一个基本类型变量或者对象的引用变量,这都在方法中的栈内存中分配;在方法(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;
      

  10.   


    new创建的对象和数组都在堆内存中存放,在堆中分配的内存由java虚拟机的自动垃圾回收器来管理,在栈中存放的是引用。方法结束,引用变量释放,堆中分配的这些对象空间等待垃圾回收机制回收。
      

  11.   


    可以看一下Properties类的源代码:    public synchronized void load(InputStream inStream) throws IOException {
            load0(new LineReader(inStream));
        }    private void load0 (LineReader lr) throws IOException {
            char[] convtBuf = new char[1024];
            int limit;
            int keyLen;
            int valueStart;
            char c;
            boolean hasSep;
            boolean precedingBackslash;        while ((limit = lr.readLine()) >= 0) {
                c = 0;
                keyLen = 0;
                valueStart = limit;
                hasSep = false;     //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
                precedingBackslash = false;
                while (keyLen < limit) {
                    c = lr.lineBuf[keyLen];
                    //need check if escaped.
                    if ((c == '=' ||  c == ':') && !precedingBackslash) {
                        valueStart = keyLen + 1;
                        hasSep = true;
                        break;
                    } else if ((c == ' ' || c == '\t' ||  c == '\f') && !precedingBackslash) {
                        valueStart = keyLen + 1;
                        break;
                    } 
                    if (c == '\\') {
                        precedingBackslash = !precedingBackslash;
                    } else {
                        precedingBackslash = false;
                    }
                    keyLen++;
                }
                while (valueStart < limit) {
                    c = lr.lineBuf[valueStart];
                    if (c != ' ' && c != '\t' &&  c != '\f') {
                        if (!hasSep && (c == '=' ||  c == ':')) {
                            hasSep = true;
                        } else {
                            break;
                        }
                    }
                    valueStart++;
                }
                String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
                String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
        put(key, value);
    }
        }可以看到,Proerties.load()方法并没有在Proerties实例对象中保存一个指向这个传入的文件流参数的引用,但它被用来创建了一个LineReader对象,那么在这个LineReader对象中可能保存有指向这个传入的文件流参数的引用。但这个LineReader对象也仅仅作为一个参数传入load0()方法,而load0()方法中未保存一个指向此LineReader对象的引用。所以load0()执行结束后,LineReader对象无其他外部引用,将被JVM回收。LineReader对象回收后,文件流对象无其他外部引用也将被JVM回收。