`
躁动的绵羊
  • 浏览: 94296 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

讨论:单例和静态方法的深入讨论

阅读更多
    常在论坛上看见一些有关单例模式、静态类、静态方法缺点的讨论,说得最多的无非是使用static,破坏了面向对象的多态性,建议除非确定了该对象不会被扩展,否则不要使用单例模式、静态方法等。其中,举例最多的是:辅助类可采用单例、静态方法

     确实,我在开发中,看见的基本都是如此。但我一直有点疑问,今天在这提出,希望JE上兄弟讨论下:

    辅助类使用静态方法就一定好吗?我觉得可能也会存在如下问题:

    1.如果类中属性或方法是static的,那么在该类被装载到方法区时,是要分配内存的。那如果是static的,是不是表示该类(非对象)永远不会被垃圾收集了呢?从而占用一定的内存空间,如果这样的类多的话,那JVM的可使用内存不是会很少?既然这样,又何必用静态方法呢?(我不太确定含有静态字段或方法的类是否会被垃圾收集器收集
   
    2. 问题1一出现,则会衍生出问题2来,即由于加载到方法区中的类型都保持着一个对加载该类的类加载器的引用,既然类不能被垃圾收集,从而则一定会造成其对应的类加载器也不会被垃圾收集,这样,又会出现许多类加载不能被垃圾收集,不是更占有JVM内存空间了吗?
由于Java的安全性特点,加载不同包下的类的加载器一定不会是同一个对象吧。这个我不确定)。

    基于以上问题,希望JE兄弟赏脸,讨论下。

    先贴出我的观点:辅助类采用单例或静态天方法也不一定是最完美的。使用单例、静态的目的就是为了节省JVM内存,如果一个辅助类用的概率不是特别大,难道还应该向大部分人建议那样使用单例或静态吗?不应该了吧。







分享到:
评论
45 楼 hapychina 2012-08-11  
static属性和方法要分配内存,不是static的就不分配了?第一次用到一个对象,或者用到静态方法,都会去加载它,不加载你你怎么用???

是不是static属性,只要没有别的对象引用你,那都会被回收,没有区别。

说下区别:一个类加载时,所有static属性修饰的引用类型,都会被加载,那不是static属性的引用类型是到new 的时候才去加载。static A a ,和 A a = new A():在加载方面是没有区别的。都是第一次用到时候才去加载A.class。

如果一个类可以做成2个样子,一个所有方法都是static的,别一个全不是。但所用到的别的对象一样,那没有区别,都是在第一次调用时去加载它们,还有它们所用到的别的对象。

属性是对别的对象的引用,是一个4字节的指针,你就是不引用别的东西,也是占4个字节。

44 楼 wupuyuan 2011-08-17  
我说说我的看法吧。
1、物理内存角度来说,加载代码的内存消耗在整个系统的消耗来说永远是小的一部分。比如jdk的总大小也有几百兆,所以开发的时候完全不用纠结一个方法是不是静态的对内存的压力大小。
2、从JVM加载类来看,方法都保存在方法区,static标记的方法是引向自身的常量池,或者说,方法加载的过程是一样的,只是提供给外部调用的形式不一样。不知道这么说是不是有错误啊,我的意思是,需要引用别的类的方法的时候,当前框架里会生成一个新框架/栈,在新的框架/栈里加入引用目标的方法,无论目标的方法是不是static,都会压入栈再被调用。
3、从设计角度来说,多态,面向对象等概念也是相对的,不是说什么都应该多态。结合实际的业务,比如某些业务逻辑制定唯一不可修改的校验方法也是常用的选择。
4、从代码角度来说,静态方法调用不需要new,调用起来相对简单点。可读性也强一点。毕竟继承/实现了N多次的class和interface读起来不是那么一目了然。
5、最后给个建议,比如有个ToolClass中,LZ要是纠结于方法是static好呢还是动态好,给个办法,ToolClass中的方法全非static,在需要它的类中这么做:
private static ToolClass tc = new ToolClass();
在需要的类中工具类是静态不用多次new的。

顺便向和LZ多讨论讨论JVM相关,如果有错误请拍砖。
43 楼 buptwhisper 2011-01-14  
mercyblitz 写道
buptwhisper 写道
接着上面的讲
静态变量是储存在类对象中的,相对于实例变量来说,静态变量只有一个,实例变量是一个实例一个,选择什么?看需求!如果你只是想调用某个与实例变量没有关系的方法,如果方法是普通的,则必须构造一个对象,再调用,这显然有些浪费,因为这个实例变量你用不着,即这个实例对象也是用不着的,还好jvm会很好的回收这些东西,这时如果考虑静态的,完全不用new一个实例对象出来,直接使用该方法就ok了,当然了,你是在无意间与对应的Class对象打交道;再考虑单例,这时是存在一个实例的,这个实例与普通的实例实质上没有差别,只是它只能存在一个罢了;这样在实例内部你可以有状态,且修改这些状态,这看你需求了;而如果把这些状态变为静态变量,相当于从实例对象移到类对象中,这从储存的角度上讲,没差别



静态对象和实例对象只是生命周期不同,除了原生类型以外,都是对象实例。

变量是元信息,通过反射得到,比如字段、方法和构造器,他们是动静之分的。只有数据的范围不同而已。


是的,如果是对象,那么储存的只是地址,相应的对象是在堆中的其它对象中储存的

42 楼 mercyblitz 2011-01-14  
buptwhisper 写道
接着上面的讲
静态变量是储存在类对象中的,相对于实例变量来说,静态变量只有一个,实例变量是一个实例一个,选择什么?看需求!如果你只是想调用某个与实例变量没有关系的方法,如果方法是普通的,则必须构造一个对象,再调用,这显然有些浪费,因为这个实例变量你用不着,即这个实例对象也是用不着的,还好jvm会很好的回收这些东西,这时如果考虑静态的,完全不用new一个实例对象出来,直接使用该方法就ok了,当然了,你是在无意间与对应的Class对象打交道;再考虑单例,这时是存在一个实例的,这个实例与普通的实例实质上没有差别,只是它只能存在一个罢了;这样在实例内部你可以有状态,且修改这些状态,这看你需求了;而如果把这些状态变为静态变量,相当于从实例对象移到类对象中,这从储存的角度上讲,没差别



静态对象和实例对象只是生命周期不同,除了原生类型以外,都是对象实例。

变量是元信息,通过反射得到,比如字段、方法和构造器,他们是动静之分的。只有数据的范围不同而已。

41 楼 buptwhisper 2011-01-14  
接着上面的讲
静态变量是储存在类对象中的,相对于实例变量来说,静态变量只有一个,实例变量是一个实例一个,选择什么?看需求!如果你只是想调用某个与实例变量没有关系的方法,如果方法是普通的,则必须构造一个对象,再调用,这显然有些浪费,因为这个实例变量你用不着,即这个实例对象也是用不着的,还好jvm会很好的回收这些东西,这时如果考虑静态的,完全不用new一个实例对象出来,直接使用该方法就ok了,当然了,你是在无意间与对应的Class对象打交道;再考虑单例,这时是存在一个实例的,这个实例与普通的实例实质上没有差别,只是它只能存在一个罢了;这样在实例内部你可以有状态,且修改这些状态,这看你需求了;而如果把这些状态变为静态变量,相当于从实例对象移到类对象中,这从储存的角度上讲,没差别
40 楼 buptwhisper 2011-01-14  
我来讲讲我的想法吧:
单例的存在是为了什么?静态方法与静态变量又是什么?
单例中一定存在静态变量与静态方法,所以可以认为单例只是静态变量与静态方法的一种使用方式;进一步的可以讨论一下静态变量与静态方法。
静态变量,即类成员变量,它的意义在于这个类下的所有成员都共享该变量,为什么要共享?这是需求决定的!java只是提供了这么一种机制。好的,再说说静态方法,也就是类方法,方法的目的在于提供一个功能,即输入什么,再输出什么,同样的我们知道静态方法能操作的只能是静态变量,这是显然的,类方法没有办法从它的某个实例取得实例的某个状态或成员变量。再讲讲它们的储存,静态变量与普通变量,静态变量是类的,所有实例包括这个类所共享的,它储存在对应的Class对象中;普通变量是实例独享的,是储存在自己的对象的状态中的。那么方法呢,我们都知道方法都是存在方法区的,不管是静态的还是普通的,所以这点上看,静态方法与普通方法在储存上并没有差别;我们的重点可以转回到静态变量与普通变量。当然这也解决了楼主的一些问题,static的方法,即一些共具类的方法,普通的与static的并没有差别。
39 楼 随影清风 2011-01-11  
我的理解, 单例就是 static的封装, 然后只提供get方法供调用。。
举个例子,
public static User user ;
这时候我们如果其他地方出现如下代码:
   val = null ;
这时候不就改变了val的值了。。

如果使用单例,
private static User user ;
public getVal(){
   if(val==null){
       user = new User();
   }
   return va;
}
这时候,使用者只能获取而不能改变它的值。

  所以,使用单例只是保护这个变量而已。。

至于和空间之类的什么关系,我真不知道,无论单例还是static ,最后不都是一个 静态变量 。。
38 楼 veenter 2011-01-11  
单例模式的出现,最开始是因为老版本的jvm在new对象的时候性能很不好,于是出现了单例模式!但是现在单例往往是做为服务类存在,往往需要多态但又不需要多实例的场景!
静态做为辅助类,在不需要多态的情况下使用静态!


其实现在项目中,楼主担心的问题基本可以忽略真真的程序瓶颈不是这些。
37 楼 veenter 2011-01-11  
kevin1988620 写道
对于类的内存占用,一向不再考虑的范围内,我在学校折腾java项目时,一向不管三期二十一,把hibernate,spring的jar包不加选择扔到lib下面。与这些jar中的类相比,自己设计的几个辅助类,实在是忽略不计。
而且如果运气不好,碰上out of memery,permgen space的时候,调整一下permsize就可以了。
我觉得内存方面主要要顾及的是往内存的static区域方对象,而不是类


你这个习惯工作中要注意了!很危险的!
36 楼 veenter 2011-01-11  
真实环境中,大量的service靠spring实例化(单例)存在,试问不都是单例存在吗!你会觉得不合适吗?
35 楼 mercyblitz 2011-01-11  
star385 写道
mercyblitz 写道
star385 写道
mercyblitz 写道
star385 写道
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?


。。。。 你的操作系统1G内存吗? Eclipse都可以上1G以上。

不想跟你做意气之争,你素质太低,
就事论事地说一下吧,
除去操作系统级别的进程和线程,你不可能只单独运行一个程序,
就以Java程序来说,你至少还需要运行虚拟机,运行虚拟机还需要相关的支持程序,
假如这些程序都需要占用1G以上,你有几个1G,
我见过一个公司的服务器,内存也才64G,
我都说了,代码行数和内存占用量没有直接联系,你还举那个例子有意义吗?



没有实际经验别下起哄,还说别人素质低!(如果说的素质低,你可以看下我的回帖)

只有你的系统内存1G,JVM是禁止使用-Xmx1024M的,注意这里是Heap的大小,还不是整个JVM的大小。

给你一个例子:

java -Xmx2048m -Xms2048m

JVM启动的时候就利用了2G以上的内存。

这样的例子很多,难道一个10G的系统,只能给它1G的内存?要知道在X64的系统中,一个Object的对象占用64bit。

留4G内存给系统就足够了。


star385 写道
代码行数和内存占用量没有直接联系


也有关系的,一般的对象放在Heap区,但是还有JVM进程的Heap,代码有一个Code generation区,元信息放在Permanent区域。如果程序使用(可能是第三方包)字节码提升的话,要加Permanent区。-XX:PermSize。

说话的时候,有理有据,不知道还有瞎说,别人自然不会理睬你。(你想想为什么“超级潜水员”会那么说吧)


好,对于技术之争,就此作罢,
或许你误解了素质低的意思,
一个人的素质往往体现在他对待自己认为错误的观点的态度,
如果你认为我的观点是错误的,你可以用各种论据推翻我的观点,
而不是用侮辱的语言去损害别人的人格,
一个人发表过一次你不认同的观点,他不是SB,
发表过十次也不是,
对持有不同观点的人进行无礼谩骂的人往往才是。




昨天晚上很晚回的,没有力气了,:-)!

我没有别的意思,就是问你的OS的问题。哥们你误会了,有伤害你的地方,向你道歉哦!
34 楼 star385 2011-01-11  
mercyblitz 写道
star385 写道
mercyblitz 写道
star385 写道
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?


。。。。 你的操作系统1G内存吗? Eclipse都可以上1G以上。

不想跟你做意气之争,你素质太低,
就事论事地说一下吧,
除去操作系统级别的进程和线程,你不可能只单独运行一个程序,
就以Java程序来说,你至少还需要运行虚拟机,运行虚拟机还需要相关的支持程序,
假如这些程序都需要占用1G以上,你有几个1G,
我见过一个公司的服务器,内存也才64G,
我都说了,代码行数和内存占用量没有直接联系,你还举那个例子有意义吗?



没有实际经验别下起哄,还说别人素质低!(如果说的素质低,你可以看下我的回帖)

只有你的系统内存1G,JVM是禁止使用-Xmx1024M的,注意这里是Heap的大小,还不是整个JVM的大小。

给你一个例子:

java -Xmx2048m -Xms2048m

JVM启动的时候就利用了2G以上的内存。

这样的例子很多,难道一个10G的系统,只能给它1G的内存?要知道在X64的系统中,一个Object的对象占用64bit。

留4G内存给系统就足够了。


star385 写道
代码行数和内存占用量没有直接联系


也有关系的,一般的对象放在Heap区,但是还有JVM进程的Heap,代码有一个Code generation区,元信息放在Permanent区域。如果程序使用(可能是第三方包)字节码提升的话,要加Permanent区。-XX:PermSize。

说话的时候,有理有据,不知道还有瞎说,别人自然不会理睬你。(你想想为什么“超级潜水员”会那么说吧)


好,对于技术之争,就此作罢,
或许你误解了素质低的意思,
一个人的素质往往体现在他对待自己认为错误的观点的态度,
如果你认为我的观点是错误的,你可以用各种论据推翻我的观点,
而不是用侮辱的语言去损害别人的人格,
一个人发表过一次你不认同的观点,他不是SB,
发表过十次也不是,
对持有不同观点的人进行无礼谩骂的人往往才是。
33 楼 mercyblitz 2011-01-11  
star385 写道
mercyblitz 写道
star385 写道
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?


。。。。 你的操作系统1G内存吗? Eclipse都可以上1G以上。

不想跟你做意气之争,你素质太低,
就事论事地说一下吧,
除去操作系统级别的进程和线程,你不可能只单独运行一个程序,
就以Java程序来说,你至少还需要运行虚拟机,运行虚拟机还需要相关的支持程序,
假如这些程序都需要占用1G以上,你有几个1G,
我见过一个公司的服务器,内存也才64G,
我都说了,代码行数和内存占用量没有直接联系,你还举那个例子有意义吗?



没有实际经验别下起哄,还说别人素质低!(如果说的素质低,你可以看下我的回帖)

只有你的系统内存1G,JVM是禁止使用-Xmx1024M的,注意这里是Heap的大小,还不是整个JVM的大小。

给你一个例子:

java -Xmx2048m -Xms2048m

JVM启动的时候就利用了2G以上的内存。

这样的例子很多,难道一个10G的系统,只能给它1G的内存?要知道在X64的系统中,一个Object的对象占用64bit。

留4G内存给系统就足够了。


star385 写道
代码行数和内存占用量没有直接联系


也有关系的,一般的对象放在Heap区,但是还有JVM进程的Heap,代码有一个Code generation区,元信息放在Permanent区域。如果程序使用(可能是第三方包)字节码提升的话,要加Permanent区。-XX:PermSize。

说话的时候,有理有据,不知道还有瞎说,别人自然不会理睬你。(你想想为什么“超级潜水员”会那么说吧)

32 楼 star385 2011-01-11  
mercyblitz 写道
star385 写道
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?


。。。。 你的操作系统1G内存吗? Eclipse都可以上1G以上。

不想跟你做意气之争,你素质太低,
就事论事地说一下吧,
除去操作系统级别的进程和线程,你不可能只单独运行一个程序,
就以Java程序来说,你至少还需要运行虚拟机,运行虚拟机还需要相关的支持程序,
假如这些程序都需要占用1G以上,你有几个1G,
我见过一个公司的服务器,内存也才64G,
我都说了,代码行数和内存占用量没有直接联系,你还举那个例子有意义吗?
31 楼 超级潜水员 2011-01-10  
star385 写道
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?



不知道你是不是极品至极点了? 你有见过多少程序是有几亿行代码的?

自古SB出二楼,真没错,附赠你一条咨讯。


【赛迪网讯】10月23日消息,一项分析发现,在最近发布2.6.27版本Linux内核之后,包括Linux内核文件在内的源代码行数已经超过了1000万行。
30 楼 mercyblitz 2011-01-10  
star385 写道
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?


。。。。 你的操作系统1G内存吗? Eclipse都可以上1G以上。
29 楼 star385 2011-01-10  
超级潜水员 写道
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?

天哪,如果一个程序假如就能占1G内存的话,完蛋了,还让不让操作系统干活了?
占内存的多少根代码行数没有直接关系吧
while (true) {
    Object o = new Object();
}
三行代码能占多少内存?
28 楼 mercyblitz 2011-01-10  
躁动的绵羊 写道
mercyblitz 写道
aabcc 写道
躁动的绵羊 写道
aabcc 写道
imacback 写道
aabcc 写道
按我的理解,ClassLoader中,如果调用了 defineClass后就不能在该 ClassLoader中remove了

前面几位高手都说能卸载,求教卸载类的方法...

按我的理解,被ClassLoader装载过的类应该是有被ClassLoader中不可操作的强引用所引用,只有在classLoader本身被GC时,被该CLASSLOADER装载过的CLASS才有可能被GC(还要排除ClassLoader以外没有任何强引用去引用该class)

如果我理解错了,求批。


是这样吗?没有任何引用的时候就会被GC掉,跟加载他的CLASSLOADER没关系吧。


// The classes loaded by this class loader.  The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private Vector classes = new Vector();





   又出现分支了:到底是类先被卸载还是该类的转载类(classLoader)先被卸载呢?
   我一直这样认为的:只有类被GC了,则就没有对它的classLoader对象的引用了,于是classLoader就会被GC
  


class 是被 classLoader 引用的, class 没引用 classLoader。

一个 实例是否被 GC 跟 实例里面的 成员 是否被 GC 没关系。

你这种理解我表示很费解。

退一百步说,假如你的 成员是 弱引用 或者 软引用,成员被 GC了,对你的实例 是否被GC 没有判定上的影响,你的实例 还是 照 GC算法来 判定是否 入GC队列。



当调用ClassLoader#defineClass方法时,会释放前面一个版本的Class!



引用
class没引用classLoader


这个我不太同意,我看《深入JVM》上写的是每个Class都有一个对其classLoader的引用。
证明: Class的 class.getClassLoader() 则说明了以上结论




字段引用只是一个标识,真正的对象Java代码级别是没有办法知道的。

按照你的理论的话,数组对象是不是要重复N个对象呢?
27 楼 kidneyball 2011-01-10  
1. lz的辅助类多到引起堆溢出,那还叫辅助类吗。简直就是过程式编程了。。。

2. 所谓“单例模式”,是类上有一个static的获取实例的方法且没有公开的构造器,而不是里面所有的方法都是static的。

3.
引用
经过对堆内存的分析,发现有大量的装载类对象没有被回收,而我的项目中使用了大量的辅助类(里面方法为static的)

ClassLoader对象没有被回收,跟被这个装载类所装载的类是否使用单例实现没有关系,跟类里面是否使用了static方法也没有关系。lz真正的关注点应该项目里是否自己创建了ClassLoader实例,并且出现了泄漏。如果没有,就看看没有被回收的ClassLoader究竟是谁实现的(全类名),在哪里创建的,是否持有大尺寸的内部属性(可能是第三方包的ClassLoader实例泄漏)。正常情况下,随便启动个应用服务器(tomcat之类),就可能load进去上千个类,也没听过会出现ClassLoader实例溢出的情况。在是否使用单例的角度去讨论是解决不了lz的问题的。

4.
引用
证明: Class的 class.getClassLoader() 则说明了以上结论

请看java.lang.Class的代码
    public ClassLoader getClassLoader() {
        ClassLoader cl = getClassLoader0();
        if (cl == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader ccl = ClassLoader.getCallerClassLoader();
            if (ccl != null && ccl != cl && !cl.isAncestor(ccl)) {
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
            }
        }
        return cl;
    }

    native ClassLoader getClassLoader0();

这样的实现代码是不能证明Class中持有了ClassLoader的引用的。
26 楼 躁动的绵羊 2011-01-10  
mercyblitz 写道
aabcc 写道
躁动的绵羊 写道
aabcc 写道
imacback 写道
aabcc 写道
按我的理解,ClassLoader中,如果调用了 defineClass后就不能在该 ClassLoader中remove了

前面几位高手都说能卸载,求教卸载类的方法...

按我的理解,被ClassLoader装载过的类应该是有被ClassLoader中不可操作的强引用所引用,只有在classLoader本身被GC时,被该CLASSLOADER装载过的CLASS才有可能被GC(还要排除ClassLoader以外没有任何强引用去引用该class)

如果我理解错了,求批。


是这样吗?没有任何引用的时候就会被GC掉,跟加载他的CLASSLOADER没关系吧。


// The classes loaded by this class loader.  The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private Vector classes = new Vector();





   又出现分支了:到底是类先被卸载还是该类的转载类(classLoader)先被卸载呢?
   我一直这样认为的:只有类被GC了,则就没有对它的classLoader对象的引用了,于是classLoader就会被GC
  


class 是被 classLoader 引用的, class 没引用 classLoader。

一个 实例是否被 GC 跟 实例里面的 成员 是否被 GC 没关系。

你这种理解我表示很费解。

退一百步说,假如你的 成员是 弱引用 或者 软引用,成员被 GC了,对你的实例 是否被GC 没有判定上的影响,你的实例 还是 照 GC算法来 判定是否 入GC队列。



当调用ClassLoader#defineClass方法时,会释放前面一个版本的Class!



引用
class没引用classLoader


这个我不太同意,我看《深入JVM》上写的是每个Class都有一个对其classLoader的引用。
证明: Class的 class.getClassLoader() 则说明了以上结论

相关推荐

Global site tag (gtag.js) - Google Analytics