`
毕竟红尘
  • 浏览: 12770 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

证明:同一个JVM里面一个Class可以被load多次

阅读更多

    对CLASSLOADER有过研究的人都知道,JVM使用CLASSLOADER在JVM中分隔出许多命名空间,不同的命名空间中的类是不“互见的”,这个“不互见”的意思是彼此不知道对方的存在,比如classloader1加载类A,在classloader2所构建的命名空间里面类就不知道的。classloader2因为不知道classloader2加载了A,所以它自己也可以以自己的方式来加载“另一个”类A。这样其实,在JVM内就存在两个Class A了。、

    上面的理论其实在看过“深入JVM”后就知道了。最近又翻了翻这本书,想起两年前与同事说的那句话“JVM可以loader两个同样的类,那你证明下呀”,当时没当回事,反正也是懵懵懂懂证明不了,避而不谈。现在呢,有时间也有能力了,那就来证明下吧。

     这个证明的逻辑是:

    因为class在被加载的时候,其static域会被初始化,那么一个类被加载两次加载进jvm的话,那么static域就会被初始化两次。

    那现在只要证明static的域是可以被初始化两次就可以了。那怎么证明呢?

    只要每次在初始化的时候能给static域赋上不同的值,区分出来,在特定的时候打印出来

就可以了。

    看下下面的代码片段,事情可能就清楚了。

    被加载的类 IntProducer:
  
import java.util.Random;

  public class IntProducer
  {
        //用随机值来加载静态域赋值,如果被加载两次age应该会是不同的值
	public static int age = getRandom();

	public static int getRandom()
	{
		Random ran = new Random(System.nanoTime());
		int rand = ran.nextInt(10);
		System.out.println("IntProducer 被加载,产生随机数:"+rand);
		return rand;

	}

 }


   用于加载IntProducer的类:


 
public class LoaderSample4
{

	public static void main(String[] args) throws Exception
	{
	    System.out.println(LoaderSample4.class.getClassLoader());
		
		
		URL[] us =
		{ new URL("file://D:/") };

		ClassLoader loader1 = new URLClassLoader(us);
		Class c1 = loader1.loadClass("IntProducer");

		System.out.println(c1.getClassLoader()+":"+c1.getField("age").getInt(c1));

		//再加载一次
		ClassLoader loader2 = new URLClassLoader(us);
		Class c2 = loader2.loadClass("IntProducer");
		System.out.println(c2.getClassLoader()+":"+c2.getField("age").getInt(c2));

	}

}



  

     
   
   

   
分享到:
评论
3 楼 Firklaag 2010-08-09  
确实是两个类,,但是为什么只初始化一次?
2 楼 wu_quanyin 2010-06-13  
sun.misc.Launcher$AppClassLoader@19821f
IntProducer 被加载,产生随机数:5
sun.misc.Launcher$AppClassLoader@19821f:5
sun.misc.Launcher$AppClassLoader@19821f:5

这是我执行的结果,,,加载一次????
1 楼 sword_ljx 2009-01-08  
在一个JVM里,两个Class是否相同不能通过通过它的名字(package+classname)相等来决定。
你的例子里,相同是Class的二进制表示,通过两个不同的CL加载之后这两个类已经不一样。
所以,是两个类,而不是一个类。

引用jvm spec(2nd)的一段话:
At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface.



相关推荐

    JVM执行子系统原理

    - **栈帧**:每个线程都有一个独立的虚拟机栈,栈中存放的是一个个栈帧,每个栈帧代表一次方法调用。 - **局部变量表**:保存方法参数和局部变量。 - **操作数栈**:用于临时存放计算过程中的中间结果。 **方法调用...

    深入理解JVM

    JVM的设计目标是实现“一次编写,到处运行”。 2. **类加载机制**:JVM通过类加载器将.class文件加载到内存中。这包括加载、验证、准备、解析和初始化五个阶段。双亲委派模型是类加载器的基本工作模式,确保了类的...

    java虚拟机简介 jvm介绍

    新创建的对象通常分配在年轻代,经过多次垃圾回收后未被回收的对象会被晋升到老年代。 2. **内存碎片处理**:JVM通过垃圾回收机制来减少内存碎片,提高内存利用率。 3. **内存分配策略**:为了提高性能,JVM可能会...

    面试必问之jvm与性能优化.pdf

    深拷贝是指完全复制一个对象及其内部引用的对象,形成完全独立的新对象。这样即使原始对象发生变化,也不会影响到拷贝后的对象。 总之,在Java开发过程中,深入了解JVM的类加载机制以及相关的类加载器类型对于提高...

    resin-jvm 调优

    在Bea安装完毕的目录下可以看到有一个类似于jrockit81sp1_141_03的文件夹。这就是Bea新JVM所在目录。不同于HotSpot把Java字节码编译成本地码,它预先编译成类。JRockit还提供了更细致的功能用以观察JVM的运行状态,...

    开源项目-zxh0-jvm.go.zip

    1. **Java虚拟机(JVM)**:JVM是Java平台的核心组件,它负责执行Java字节码,提供了一个跨平台的运行环境。JVM实现了内存管理、垃圾回收、类加载机制等,确保了Java程序的“一次编写,到处运行”。 2. **Go语言**...

    tEST_ALOAD_1.RAR_The Test

    标题中的“tEST_ALOAD_1.RAR_The Test”可能是一个测试压缩文件,其中包含了名为“Test_aload_1.java”的源代码文件。在Java编程语言中,".java"文件是源代码文件,用于编写Java应用程序。"ALOAD"在Java字节码中是一...

    JVM与性能优化知识点整理.pdf

    当对象在新生代中经过多次GC仍然存活下来时,将会被提升到老年代。 - **永久代**:在Java 8之前,用于存放类元数据,包括类定义、常量池、静态变量等信息。在Java 8中已被元空间(Metaspace)取代。 #### 四、编写...

    2024年java面试题-jvm性能调优面试题第二部分

    - **老年代(Old Generation)**:对象在新生代经过多次垃圾回收后,或者较大的对象直接被分配到老年代。 2. **栈区(Stack)**:栈区主要用于存储线程私有的数据,例如局部变量表、操作数栈、动态链接、方法出口等...

    class文件结构(简单class文件)

    紧随魔术数之后,是两个字节的版本信息,分别表示主版本号和次版本号,主版本号表示class文件可以被执行的JVM版本,次版本号表示class文件的兼容性。class文件中的版本信息告诉JVM运行class文件的Java环境版本。 接...

    JVM内存资料.zip_jdk

    而小对象则可能在Eden区快速分配,经历一次或多次Minor GC后晋升到老年代。如果对象在 Eden 区分配失败,且Survivor区也无法容纳,就会触发Full GC,这通常是性能问题的潜在信号。 通过JDK源码分析,我们可以了解到...

    deepinJvm-zzm:周志明,深入理解JVM的源代码

    《深入理解JVM的源代码》是周志明先生的一部深度解析Java虚拟机(JVM)的经典著作。这本书以源代码为线索,详细剖析了JVM的工作原理,旨在帮助开发者深入理解Java运行机制,提升程序性能优化的能力。在本文中,我们...

    01-JVM综合53问(带答案)

    【JVM综合53问】是一份针对Java虚拟机(JVM)的全面问答文档,旨在帮助Java开发者深入理解和优化JVM。以下是其中涉及到的一些关键知识点: 1. **为何学习JVM?** - **面试需求**:在招聘中,企业越来越重视技术...

    阿里面试题 JVM-开源框架.docx

    2. **JVM内存结构**:JVM内存主要分为堆内存(包括新生代和老年代)和栈内存(每个线程一个栈),还有方法区(包含持久代)。新生代进一步划分为Eden区和两个Survivor区(From和To),默认比例为8:1:1。 3. **内存...

    java虚拟机源码-jvm-demo-code:深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)源代码

    例如,`aload_0`用于从局部变量表中加载第一个引用类型变量,`iadd`用于执行加法操作。源代码会包含各种字节码指令的示例,以帮助理解它们如何协同工作。 4. 内存管理:JVM的内存管理主要包括垃圾收集(Garbage ...

    Java虚拟机简介.pdf

    2. 类加载器(classloader):JVM内部包含一个或多个类加载器,用于加载Java类文件(.class文件),并将类信息加载到JVM中。类加载器在Java中是一种动态加载类的方式,是实现JVM跨平台能力的重要组件。 3. 字节码...

    java之反射优化(缓存思路)源码

    当频繁地使用相同的反射操作时,如获取Class对象、构造函数或方法,预加载这些信息并存储在一个缓存中可以显著提高性能。这种缓存机制减少了重复的JVM查找,从而降低了运行时的开销。 缓存思路通常有以下几种实现...

    阿里面试题总结和答案整理

    - 老年代:存放经过多次GC后存活下来的对象。 - 持久代(Permanent Generation):存放类元数据,如类定义、常量池等。(注:Java 8中已改为元空间) #### 9. GC用的引用可达性分析算法中,哪些对象可作为GC ...

    Java字节码揭秘

    可以通过不同类加载器加载同一个类的不同版本。 2. **线程上下文类加载器** - **默认设置**:通常默认为系统类加载器。 - **用途**:主要用于资源和服务提供者 SPI(Service Provider Interface)的实现类加载。...

Global site tag (gtag.js) - Google Analytics