① java中的“类”是什么时候被加载到虚拟机
1、编译和运行概念要搞清:编译即javac的过程,负责将.java文件compile成.class文件,主要是类型、格式检查与编译成字节码文件,而加载是指java *的过程,将.class文件加载到内存中去解释执行,即运行的时候才会有加载一说。
2、类的加载时机,肯定是在运行时,但并不是一次性全部加载,而是按需动态,依靠反射来实现动态加载,一般来说一个class只会被加载一次,之后就会从jvm的class实例的缓存中获取,谁用谁取就可以了,不会再去文件系统中加载.class文件了。
② Java中类加载出现在哪个阶段,编译期和运行期 类加载和类装载是一样的吗
使用的类,编译/运行时都会被加载。
加载/装载没有区别,翻译的词汇选择因人而异了
运行 javac /java 时 加上 -verbose 选项就可以看到了。
③ 怎么理解java中的静态加载类和动态加载类
一.什么是动态加载类 什么是静态加载类
Class.forName 不仅表示类的类类型,还代表了动态加载类。编译时加载是静态加载类,
运行时加载是动态加载类。
二.为何要使用动态加载类
我们写了一个程序 并没有写A类和B类以及start方法?
④ java 类加载先后顺序
1.父类静态代码块;
2.子类静态代码块;
3.父类非静态代码块;
4.父类构造函数;
5.子类非静态代码块;
6.子类构造函数;
举例:
public class ExA {
static {
System.out.println("父类静态代码块。");
}
public ExA() {
System.out.println("父类构造函数。");
}
{
System.out.println("父类非静态代码块。");
}
public static void main(String[] args) {
new ExB();
}
}
class ExB extends ExA {
static {
System.out.println("子类静态代码块。");
}
{
System.out.println("子类非静态代码块。");
}
public ExB() {
System.out.println("子类构造函数。");
}
}
执行结果:父类静态代码块。子类静态代码块。父类非静态代码块。父类构造函数。子类非静态代码块。子类构造函数。
⑤ java 类加载机制有什么用
AVA类加载机制详解
“代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是变成语言发展的一大步”,这句话出自《深入理解JAVA虚拟机》一书,后面关于jvm的系列文章主要都是参考这本书。
JAVA源码编译由三个过程组成:
1、源码编译机制。
2、类加载机制
3、类执行机制
我们这里主要介绍编译和类加载这两种机制。
一、源码编译
代码编译由JAVA源码编译器来完成。主要是将源码编译成字节码文件(class文件)。字节码文件格式主要分为两部分:常量池和方法字节码。
二、类加载
类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。过程共有七个阶段,其中到初始化之前的都是属于类加载的部分
加载----验证----准备----解析-----初始化----使用-----卸载
系统可能在第一次使用某个类时加载该类,也可能采用预加载机制来加载某个类,当运行某个java程序时,会启动一个java虚拟机进程,两次运行的java程序处于两个不同的JVM进程中,两个jvm之间并不会共享数据。
1、加载阶段
这个流程中的加载是类加载机制中的一个阶段,这两个概念不要混淆,这个阶段需要完成的事情有:
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在java堆中生成一个代表这个类的Class对象,作为访问方法区中这些数据的入口。
由于第一点没有指明从哪里获取以及怎样获取类的二进制字节流,所以这一块区域留给我开发者很大的发挥空间。这个我在后面的类加载器中在进行介绍。
2、准备阶段
这个阶段正式为类变量(被static修饰的变量)分配内存并设置类变量初始值,这个内存分配是发生在方法区中。
1、注意这里并没有对实例变量进行内存分配,实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。
2、这里设置的初始值,通常是指数据类型的零值。
private static int a = 3;
这个类变量a在准备阶段后的值是0,将3赋值给变量a是发生在初始化阶段。
3、初始化阶段
初始化是类加载机制的最后一步,这个时候才正真开始执行类中定义的JAVA程序代码。在前面准备阶段,类变量已经赋过一次系统要求的初始值,在初始化阶段最重要的事情就是对类变量进行初始化,关注的重点是父子类之间各类资源初始化的顺序。
java类中对类变量指定初始值有两种方式:1、声明类变量时指定初始值;2、使用静态初始化块为类变量指定初始值。
初始化的时机
1)创建类实例的时候,分别有:1、使用new关键字创建实例;2、通过反射创建实例;3、通过反序列化方式创建实例。
new Test();
Class.forName(“com.mengdd.Test”);
2)调用某个类的类方法(静态方法)
Test.doSomething();
3)访问某个类或接口的类变量,或为该类变量赋值。
int b=Test.a;
Test.a=b;
4)初始化某个类的子类。当初始化子类的时候,该子类的所有父类都会被初始化。
5)直接使用java.exe命令来运行某个主类。
除了上面几种方式会自动初始化一个类,其他访问类的方式都称不会触发类的初始化,称为被动引用。
1、子类引用父类的静态变量,不会导致子类初始化。
执行结果:
MIGU
用final修饰某个类变量时,它的值在编译时就已经确定好放入常量池了,所以在访问该类变量时,等于直接从常量池中获取,并没有初始化该类。
初始化的步骤
1、如果该类还没有加载和连接,则程序先加载该类并连接。
2、如果该类的直接父类没有加载,则先初始化其直接父类。
3、如果类中有初始化语句,则系统依次执行这些初始化语句。
在第二个步骤中,如果直接父类又有直接父类,则系统会再次重复这三个步骤来初始化这个父类,依次类推,JVM最先初始化的总是java.lang.Object类。当程序主动使用任何一个类时,系统会保证该类以及所有的父类都会被初始化。
⑥ java 编译通过,运行时,找不到或无法加载主类
楼主的环境变量没有什么问题,问题在于
java
hello.java
这一行,原因:
1.java
命令是运行程序的命令,它最终会调用虚拟机加载并执行
java
字节码(hello.class文件),所以如果使用
java
hello.java,这样虚拟机回去加载
hello.java这个源文件,而类加载过程会进行验证,显然这种格式是虚拟机无法识别的(虚拟机需要的是字节码文件)
2.那为什么不使用
java
hello.class
呢?因为虚拟机加载字节码文件的时候是根据你java
命令后面的字符串(也就是hello.classs),在前面加上包名,后面加上".class",然后再去加载这个字节码文件的,也就是说程序会自动在后面加上".class"后缀,所以你不用加,加了反而找不到这个文件了。
⑦ 当java程序有多个类时,具体电脑怎么编译操作执行
java类的加载是懒惰式加载
就是用到了就加载,而且只会加载一次
基本流程应该是
运行一个java程序的时候,先执行入口方法main(),然后迭代加载main()方法所在的类的父类
然后用到什么类就加载什么类
⑧ java中类的加载是在什么时候做的
楼上的负责一点好么,类加载是在编译的时候?加载一个类需要用到加载器,
你程序都没运行,jvm都没启动,哪来的加载器,你拿什么去加载一个类?
类加载的时候是运行程序时 它就加载了,至于编译,你用IDE,是你一保存,它就给编译好了。
⑨ jdk中提供了什么方法对java类文件进行编译
importjava.lang.reflect.Method;
importjava.net.URL;
importjava.net.URLClassLoader;
importjavax.tools.JavaCompiler;
importjavax.tools.ToolProvider;
publicclassDemo01{
publicstaticvoidmain(String[]args)throwsException{
JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();
intresult=compiler.run(null,null,null,"C:/source/HelloWorld.java");
System.out.println(result==0?"编译成功":"编译失败");
URL[]urls=newURL[]{newURL("file:/"+"C:/source/")};
URLClassLoaderclassLoader=newURLClassLoader(urls);
Class<?>clazz=classLoader.loadClass("HelloWorld");
//调用main方法
Methodm=clazz.getMethod("main",String[].class);
m.invoke(null,(Object)newString[]{});
}
}
上述代码会将c盘目录下的HelloWorld.java文件编译成HelloWorld.class文件,并将其加载到JVM虚拟机中,调用main方法将其执行
⑩ java程序什么是类加载
你可以了解一下
深入理解java虚拟机,
java类加载
是因为在运行时当它需要引用某个类的时候,会先去加载这个类,就是去读这个class文件到内存里面来,现在还没有创建这个类的实例,
你可以理解为
你写的java代码在编译成class文件后,并没有去执行,或者去引用他,只有程序运行时它将要使用这个类的时候才会去读取这个class文件,这时候叫做类加载,当缓存了这个类文件之后,后面的创建类的时候都会去引用它,因为类加载是运行是加载,所以java代码在运行时是有办法修改的,同样java类加载也允许加载一个远程的class文件,也代表它是支持程序不停止时更新程序代码的。