第一次用到一个类的时候,ClassLoader会把该类加载到jvm,是吧?
那么有没有办法从jvm卸载该类呢? 
我是基于这样的考虑才提出这个问题的:比如我在应用里要用到DOMParser,但仅仅在应用开始的时候使用一次,而该类及其相关类却要一直存在,直到应用结束。这样是不是有点浪费资源? 小程序当然无所谓,但是对于一个大的应用,这个问题恐怕不能不考虑 先给20分,有回答会再增加100

解决方案 »

  1.   

    好像JVM会把经常不使用的类从内存除去,关注一下
      

  2.   

    GC是的事,当然你也可以强制执行GC
      

  3.   

    我觉得不应该由JVM自动处理,因为如果这个类有静态数据,这样会销毁静态数据
    而这很可能是我们不希望的这个问题可以给sun提一下
      

  4.   

    我只知道GC管对象的销毁,如果一个对象没有任何变量去引用它,GC就会考虑销毁它
    而且对GC的调用并不一定能立刻执行“垃圾回收”
      

  5.   

    是类,不是对象根据ClassLoader的介绍,当第一次使用外部类时,ClassLoader就会把该类加载到JVM,然后就可以创建该类的实例,即对象。类一旦加载,就会一直驻留内存,直到应用终止。我想类总会占用部分内存的,特别是对于大型应用,总要想办法高效使用内存。所以,能不能把不常用的类卸载,然后等到下次需要的时候再加载进来?
      

  6.   

    看看这儿
    http://java.sun.com/docs/books/jls/unloading-rationale.html
      

  7.   

    To flyforlove(为情飞),hbwhwang(我是catmiw的马甲):我觉得这篇文章是sun的狡辩。这种优化对于应用不应该是透明的,而应该由具体的应用自己选择,sun应该提供方便的接口方法以供特定的应用调用。另外,每启动一个java应用都要重新加载一个新的JVM。这些状况不改变的话,java的桌面开发恐怕难有太大的发展。
      

  8.   

    敲命令 java -X,能看见
        -Xnoclassgc       disable class garbage collection这也许能说明 Sun 提供的 JDK 是考虑了 class unloading 的吧……当然,这是 Sun 在实现 JVM 的时候做的扩展,并不是 Java Language Specification 的要求。我倾向与认为,class unloading 的事情应该交给 JVM 去处理,应用程序不必直接介入。
      

  9.   

    楼主上面提到的一个问题我很感兴趣:能在加载一个 Java 应用程序的时候使用一个已经在运行的 JVM 吗?如果没有现成的办法,我们自己能实现吗?
      

  10.   

    楼上这位的问题或许可以自己想办法。比如写一个程序来启动JVM,并设置为服务级的进程。然后所有的java类和jar文件都通过这个程序来运行。这个程序负责调用已有的JVM来运行这些java程序。不过,问题在于,如果一个程序崩溃了,所有的程序都会受到影响。所以,我觉得每个程序运行一个JVM还是有道理的,只是JVM如果能根据程序的需要分配资源,不是一个小小的java程序也预调入很多东西,分配很多内存就好了。
      

  11.   

    > 比如写一个程序来启动JVM,并设置为服务级的进程。
    > 然后所有的java类和jar文件都通过这个程序来运行。
    > 这个程序负责调用已有的JVM来运行这些java程序。
    > 不过,问题在于,如果一个程序崩溃了,所有的程序都会受到影响。嗯,不错,听起来挺有道理  :D但是麻烦事还是有一些的,比如,每个程序的 CLASSPATH 可能不尽相同,怎么办呢?总不能让每个程序都像 Tomcat 那样自己带一套 ClassLoader 吧?Anyway, 大体上是差不多的了。程序间的相互影响是不好解决,毕竟线程之间的隔离不像进程间隔离得那么清楚。不过在典型的桌面应用背景下(不是调试环境),多个比较成熟稳定的应用程序要是能共用一个 JVM 还是个不错的选择。相对于一个小的应用程序,JVM 的“额外开销”实在太大了,但却不能省掉,就像仅仅运行一个记事本,也必须启动整个 Windows 一样(顶多来个“安全模式”,也没小到哪去)
      

  12.   

    UnAgain() ( ) 信誉:98  2006-08-08 11:13:00  得分: 0  
     
     
       To flyforlove(为情飞),hbwhwang(我是catmiw的马甲):我觉得这篇文章是sun的狡辩。这种优化对于应用不应该是透明的,而应该由具体的应用自己选择,sun应该提供方便的接口方法以供特定的应用调用。另外,每启动一个java应用都要重新加载一个新的JVM。这些状况不改变的话,java的桌面开发恐怕难有太大的发展。  
    -------------------关键是连类的实例都是由jvm来管理的,更何况类本身呢,如果连类的实例我们都不知道什么时候释放,怎么可以去释放类呢。
    而且,我觉得在java中释放类比释放实例更加困难。
      

  13.   

    http://community.csdn.net/Expert/topic/4935/4935768.xml?temp=9.489077E-02
    我的问题:销毁一个对象的函数? 100分(楼主冒犯了)
      

  14.   

    To fzhsun(MM=Much Money):刚看了你的帖子,你既然来了,我也顺便提个疑问。iouzhui()一个“顶”字,怎么就给了50分?
      

  15.   

    加载类,类只占用其本身说明的空间,没有多少。
    A class or interface may be unloaded if and only if its class loader is unreachable. Classes loaded by the bootstrap loader may not be unloaded. 
    看来如果有必要jvm会去做这件事情。
    但我想,如果空间够用,jvm肯定不会去做,因为这个类又可能被其他的ClassLoader再次加载
      

  16.   

    楼主说,不应该透明?
    其实我觉得这就是java相对C的优势之一,对内存的直接操作都被屏蔽掉。用户不必关心
    内存的分配与回收。
    而且如果你说unload不透明,那么同时加载类又是透明的,那么程序员岂不多操心了?
    何时何地该unload?如果Reload怎么办?有线程在Reflect中调用该类,而你却把他给unload了
    那岂不是频繁unload ,reload
    本人不才,没有什么更好的想法,觉得java的GC机制很好
      

  17.   

    注:loadClass 是一个很费时费事的。
      

  18.   

    To bigc2000(公元2005年4月9日):我说的unload不透明指的是unload class,而不是unload object。我为什么强调unload class是因为我的一个小程序在开始的时候要用到一个类,然而以后不再用到。所以我考虑如果在内存紧张的情况下,最好能unload class。正是因为JVM开发者不会知道用户被unload的类会不会需要reload,所以,应该把这个功能做成不透明的,仅由开发人员自己选择。
      

  19.   

    这个问题好像很难处理,只有加载类的类加载器不可用时,加载的类才能被回收。
    所以需要自定义类加载器。void method(){
       ClassLoader loader=new MyClassLoader();
       Class c=loader.loadClass("XXXXX");
       ...
       ..
       退出之后可以被回收了
    }
    同一个类可以被不同的类加载器加载
      

  20.   


    有点意思。但是我能不能用平常的写法?比如
        MyClass myClass = new MyClass();
      

  21.   

    这个手动肯定是不行的,因为在你手动卸载的时候,JVM并不知道这个类型是否被引用,所以手动肯定不行。
    但是GC会自动卸载那些不用的类型,这个你可以看看《深入JAVA虚拟机(第二版)》中关于垃圾回收章节的叙述。
      

  22.   

    想这种问题没用,真想明白,只有去问SUN了,但它会告诉你"难道你没听过..."
    产品说明书在那,说得很明白了.冰箱厂家是不会考虑回答你如何让冰箱变烤箱的
      

  23.   

    欢迎光监点石成金网 http://www.boxigroup.com 网站提供web开发(j2ee .net asp php javascript、c#等) c/s开发(delphi、vb、vc、pb、cb等) 数据库开发(oracle、sqlserver、db2、access、mysql、Postgresql、informix)等学习资料,希望能为你解决燃眉之急 ,请把本网站加入收藏夹,以备不时查询之需 bs+cs讨论群(9638134)
      

  24.   

    To UnAgain() ( ) 信誉:98 
    我说的是类的加载,而不是类的实例加载,
    我说的是类本身的卸载,而不是类实例的内存回收。还是那句话。一个类可能被由其他线程或者本地方法加载的,假设外部可以强制卸载这个类,
    那么也就是说这个类的说明全部没有了她的相关信息也就没有了,而如果有个其他线程
    调用Class c = Class.forName("calssName");
    那么按照你的说法,改线程就必须重新加载这个类,并且初始化,而这个类的加载确实透明的(用户无法知道是不是这个类已经被加载过),这显然不符合java设计思想(让程序员远离繁琐的内存的分配与回收)
    最坏的情况是1个在unload,一个在load
      

  25.   


    我指的是如果程序员自己知道一个类在一次用过之后,可以确保以后不再使用的情况下,sun应该给程序员提供一个选择。
      

  26.   

    UnAgain() ( ) 信誉:98  2006-08-22 10:37:00  得分: 0  
     
     
       
    我指的是如果程序员自己知道一个类在一次用过之后,可以确保以后不再使用的情况下,sun应该给程序员提供一个选择。
      
     
    --------------------------------但是你都不知道类的实例什么时候释放的,你怎么可能知道这个类还有没有在用?
      

  27.   

    垃圾回收是JVM层面的事情,而且与具体的JVM实现相关,程序员是无法确知垃圾回收在何时执行,不管是对象回收还是类回收。
      

  28.   

    GC是对对象的回收而不是对类的卸载。jvm里有2种类装载器,一种是java api,可被信任的。一种是用户自定义类装载器,即用户可以调用Class.forName()装载。但是没有看见用户可以手工卸载类的方法。我想这具体jvm的的实现有关:正如GC一样,在程序里即使显示调用GC并不能保证GC一定得到执行,只有当达到某种条件时GC才执行。同样:也许jvm有类似的类卸载机制。不过现在好像没有提供接口。sun应该提供给程序员类似于GC的接口来手工对类进行卸载。
      

  29.   

    顺便问一下能不能替换jvm中的同名已加载的类呀?