Java对象创建过程
Java对象被创建有两种方式:第一种是通过new XX();第二种是Class.forName("XX").newInstance().我现在对这个流程的认识有些混乱.
要生成一个类的对象,必须有两样东西被加载到内存,一种是Class对象;另一种是类,然后类对象才会被创建.由于Java是动态加载(类的静态成员被引用,类才会别加载),所以类加载的时候相对于上面的两种方式分别是在:第一种:new XX(),因为构造器方法也是静态方法,这种方式会调用构造器方法,所以此时类会被加载;第二种:Class.forName()首先会检查类有无被加载,没有则加载类.至此,两种方式的类都被加载.
我的疑问是Class对象是何时被加载的,是和类一样吗?(我现在知道的关于Class对象的知识就是它是在.java文件被创建,被编译后产生了和类名字一样的.class文件.)是在类被加载之前还是之后,还有Class对象是怎么和类配合生成类对象的...希望大家能多多发表自己的见解.
[解决办法]
怎么说的有点乱七八糟的啊,加载类就是加载Class对象。
new XX();
Class.forName("XX").newInstance();
这两种效果一样,加载方式也一样,毫无区别,newInstance()实际上也是调用默认构造器方法的。
只是在用的场合不一样,前面一种用的很普遍。后面一种一般都是结合工厂模式应用的比较多。
[解决办法]
这两种方式效果是一样的,但是稍微有以下两点小区别:
区别1:Class.forName的方式能实现动态地载和创建Class 对象,而NEW指定生成某个类的对象
例:String str = 你定义的字符串
Class t = Class.forName(str);
t.newInstance();
区别2:JAVA的工厂模式中常使用Class.forName方式创建对象
[解决办法]
class Test{
}
还有一种方式,
Class<?> i=Test.class ;
i.newInstance();
不同之处:LZ列举上面2种都会伴随类的初始化,而这种不会伴随类的初始化。
[解决办法]
加载class二进制文件,生成该类对应的Class对象。
[解决办法]
ClassLoader读取class文件内容得到一个byte[],
然后就可以调用defineClass来在ClassLoader中生成Class
[解决办法]
http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html
[解决办法]
}
}
class LoaderTest
LoaderTest
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$ExtClassLoader@addbf1
null
首先对于编译后的LoaderTest.class,必须要知道哪个加载器来加载,(下面是一种委托模式,及子类加载器都先调用父类加载器加载)首先调用AppClassLoader来加载,但AppClassLoader会让他继承的父类加载器ExtClassLoader加载LoaderTest.class,ExtClassLoader没有父类加载器(返回值为null),将LoaderTest.class转交给虚拟内核中的Bootstrap,由于Bootstrap只能加载java核心包中的类,所以告诉ExtClassLoader自己不能加载,ExtClassLoader是用来加载%JAVA_HOME%/jre/lib/ext/中的jar包中类,自己也不能加载LoaderTest.class,于是就告诉AppClassLoader自己不能加载该LoaderTest.class。由于AppClassLoader可以加载应用程序的启动态,可以加载该LoaderTest.class,
然后就像上面说的那样,加载时生成了一个个Class类的实例对象,该Class对象封装了 LoaderTest.class的字节码数据,也就是生成存储在内存中的可执行代码。我们可以通过Class.forName("LoaderTest").getName()获得这个Class对象的名称,通过Class.forName("LoaderTest").newInstance()来获得 LoaderTest这个类的对象。
[解决办法]
类加载器为程序的执行加载所需要的全部类。类加载器将局部文件系统的类名空间与来自网络源的类名空间相分离,以增加安全性。由于局部类总是首先加载,因而可限制任何“特洛依木马”的应用。
当全部类被加载后,可执行文件的记忆体格式被确定。这时,特定的内存地址被分配给符号引用并创建检索表格。由于记忆体格式在运行时出现,因而Java技术解释器增加了保护以防止对限制代码区的非法进入。
网上找了些资料,有用的话就好了。。。
[解决办法]
java虚拟机使用每个类的第一件事就是将该类的字节码撞进来。类装载器负责根据一个类的名称来定位和生成类的字节码数据后返回给java虚拟机。如,UTF-8编码形式的.class 文件,装进java虚拟机后要被转换成Unicode 编码,装载类本身也是一个java类,当一个类被夹在后,java虚拟机将其编译成可执行代码存储在内存中,并将索引信息存储在一个HashTable中,索引关键字就是这个类的完整名称。在java虚拟机需要用到某个类时,首先通过hashtable查找相应的信息,如果该可执行代码已经存在,java虚拟机就直接从内存中调用该可执行代码,否则调用类装载器加载。
[解决办法]
在调用Class.forName("")时,类会被初始化,调用newInstance()产生类的实例
使用new时,JVM同样先初始化类,然后再产生实例
Class.forName("")是动态加载,并且被加载的类有一定的限制,它必须有一个默认的,有访问权限的无参构造器,否则会抛出异常(可以编译)
而new则相对必较灵活,它不需要默认的无参构造器,没有访问权限的话将无法编译
[解决办法]