上一节课老师讲了java类的动态装载与反射,上课时听的稀里糊涂的,课后自己找了《深入java虚拟机》看了相关的内容,今晚就大概的总结一下吧,或者说是在写读书笔记。
平时在编写并运行java程序时,就体验到相关的java技术。首先是编译器把源程序编译成java class文件,然后在java虚拟机中运行class文件。要想深刻的理解java类的动态加载与反射,首先是要理解java虚拟机的体系结构。下面是java虚拟机的体系结构图:
从图中可以看出Java虚拟机运行一个程序时,首先是通过类装载器来装载class文件的,然后从已装载的class文件中得到类的相关信息,如程序创建的对象,传递给方法的参数,返回值,局部变量等,java虚拟机将这些东西存储到运行时数据区进行管理的。
类装载器:java虚拟机中有两种类装载器:1.启动类装载器,2.用户自定义装载器。启动类装载器是java虚拟机实现的一部分,而用户自定义类装载器是普通的java对象,它的类必须派生自java.lang.ClassLoader类,ClassLoader类中定义的方法为程序提供了访问类装载器机制的接口,从ClassLoader类的源代码中可以看出主要是通过以下四个方法通向Java虚拟机的。
protected final Class<?> defineClass(String name, byte[] b, int off, int len)
throws ClassFormatError
{
return defineClass(name, b, off, len, null);
}
protected final Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain)throws ClassFormatError
{
return defineClassCond(name, b, off, len, protectionDomain, true);
}
protected final void resolveClass(Class<?> c) {
resolveClass0(c);
}
protected final Class<?> findSystemClass(String name)
throws ClassNotFoundException
{
ClassLoader system = getSystemClassLoader();
if (system == null) {
if (!checkName(name))
throw new ClassNotFoundException(name);
Class cls = findBootstrapClass(name);
if (cls == null) {
throw new ClassNotFoundException(name);
}
return cls;
}
return system.loadClass(name);
}
两个重载的defineClass方法能够把新的类或者接口导入到方法区中,findSystemClass方法通过启动类装载器来装载指定类型,resolveClass方法能够让装载器执行连接动作。此外,对于每一个被装载的类或者接口,java虚拟机都会为它创建一个java.lang.Class的实例来代表该类或者接口。用户自定义的类装载器以及Class类的实例都放在堆中,而装载的类或者接口则放在方法区中。
方法区:在java虚拟机中被装载的类或者接口的信息存储在逻辑上称为方法区的内存中,虚拟机会在方法区中存储以下类或者接口的信息:
1.这个类或者接口的权限定名。
2.这个类或者接口的直接超类的权限定名,除非java.lang.Object类。
3.这个类或者接口的的标识,即是类还是接口。
4.这个类或者接口的访问修饰符。
5.任何直接超接口的权限定名的有序列表。
6.该类或者接口的常量池。
7.字段信息。
8.方法信息。
9.除了常量以外的所有类变量。
10.一个到ClassLoader类的引用。
11.一个到Class类的引用。
堆:java程序在运行时创建的所有类的实例或数组都放在同一个堆中。在一个java虚拟机实例中,只存在一个堆空间,因此所有线程都共享这个堆,在这种情况下就要考虑多线程访问对象的同步问题了。
Java栈:每当启动一个线程时,虚拟机都会为它分配一个Java栈,虚拟机只会直接对Java栈执行两种操作:以帧为单位的压栈和出栈。
从以上的的表述中大概了解了java虚拟机的体系结构,下面大概总结下虚拟机的工作过程:
java虚拟机通过装载、连接、初始化一个java类或者接口,使得可以被正在运行的java程序所使用。其中,装载是把class文件读入虚拟机中,连接是把已读入虚拟机中的数据类型合并到虚拟机的运行时状态中去,连接分为三个阶段:验证、准备和解析,验证是确保java类型数据格式正确并使用于虚拟机,准备则是负责为该类型(类或者接口)分配所需的内存空间,解析是把常量池中的符号引用转换为直接引用。初始化是将类变量赋以适当的初始值。
装载阶段是由三个基本动作组成:
1.通过该类型的完全限定名,产生一个代表该类型的二进制数据流。
2.解析这个二进制数据流为方法区内的内部数据结构。
3.创建一个表示该类型的java.lang.Class类的实例。
总结:装载的最终产品是Class类的实例对象,它成为Java程序与内部数据结构之间的接口。
初始化包含两个步骤:
1.如果类存在直接超类,且直接超类还没有被初始化,就先初始化直接超类。
2.如果类存在一个类的初始化方法,就执行此方法。
一旦一个类被装载、连接和初始化,它就可以随时使用了,程序可以访问它的静态变量,调用它的静态方法,或者创建它的实例,在java程序中可以明确的使用new;或者调用Class或者java.lang.reflect.Constructor对象的newInstance()方法;或者调用现有对象的Clone()方法来创建对象。
java程序通过传递类型的名字到java.lang.Class的forName()的方法或者用户自定义的类装载器的loadClass()方法可以在运行时决定加载哪一个类型并使用它们。
好了,先写到这里吧,总结的很粗糙,以后有深入的理解再总结吧。
- 大小: 12.8 KB
分享到:
相关推荐
### Java集合小结 #### 一、集合的概念与重要性 集合是Java编程语言中用于存储、管理和操作数据的一种重要工具。它提供了多种数据结构来适应不同的应用场景,从而有效地提高程序开发效率。从数据结构的角度来看,...
本文主要讲述如何利用Java编程语言中的Jsoup库和HttpClient工具包来获取和解析动态生成的数据,特别是那些通过JavaScript动态加载的数据。 ### Java爬虫基础 Java爬虫是指使用Java语言编写的一类程序,这些程序...
### Java基础知识小结 #### 1.1 `getPath()`、`getAbsolutePath()`、`getCanonicalPath()`的区别 在Java中,处理文件路径时经常会用到`getPath()`、`getAbsolutePath()`以及`getCanonicalPath()`这三个方法。它们...
RMI(Remote Method Invocation,远程方法调用)是Java平台中用于分布式计算的一种技术,它允许一个Java对象调用另一个在不同 JVM(Java虚拟机)上的对象的方法,从而实现跨网络的通信。Java RMI 提供了一种透明的...
### Java笔试题小结 #### 1. Java 字符串(String) **问题**: String 类的特点是什么?与 StringBuffer 的区别? **分析与解答**: `String` 类在 Java 中是不可变的,即一旦创建了一个字符串对象,其内容就不能...
为了使Java能够识别该方法,我们需要在Java代码中加载名为“`Mytest`”的动态链接库。 #### 2. 生成C/C++头文件 接下来,通过命令行工具生成C/C++头文件: ```sh javac Mytest.java javah -jni Mytest ``` 这将...
这篇小结将深入探讨这两个关键概念,以及它们在实际编程中的应用。 首先,类是Java中的蓝图,它定义了一组特性和行为,这些特性和行为共同构成一个特定实体。类可以包含字段(或称为属性),它们代表对象的状态,...
理解类的加载、编译和运行过程有助于深入学习Java。 8. **工具实践**:理解并掌握如何使用JDK工具,如Javac编译器、Javadoc生成API文档、JAR打包工具等,能提高开发效率。 总之,Java基础涵盖了许多方面,从简单的...
### Java技巧小结荟萃 #### Javadoc API 文件产生器 Javadoc 是一款非常重要的工具,主要用于生成文档,能够从源代码注释中提取出有用的文档信息。这不仅有助于提高代码的可读性,还方便其他开发人员快速理解类、...
为了全面理解Java基础知识,本小结将按照给定的文件名,逐一解析关键知识点。 1. **Java基础知识** 这一部分通常包括Java语言的基础语法,如变量、数据类型、运算符、流程控制(if语句、switch、for、while循环等...
如果登录验证通过,可能跳转到新的界面或者加载用户信息;若验证失败,则显示错误信息。 此外,为了提高代码可读性和可维护性,通常会使用匿名内部类来创建监听器。Java 8引入了Lambda表达式,可以更简洁地编写监听...
#### 四、小结 通过上述介绍可以看出,在Java中加载文件的方式多种多样,开发者可以根据实际需求选择最适合的方法。无论是基于Java本身的类加载机制还是通过Spring等框架提供的便捷方式,都能够有效地实现资源文件...
通过定义抽象的接口或基类,可以在不修改现有代码的情况下添加新的实现,使得系统更加模块化和易于维护。 #### 总结 Java中的多态特性是面向对象编程的强大工具之一,它允许我们在编写代码时,不必关注具体的实现...
下面是对"Java中类的继承学习小结"的详细讲解。 首先,类的继承使用关键字`extends`来实现。子类(也称为派生类)声明时,会指定一个父类(或超类): ```java public class DerivedClass extends BaseClass { //...
Java 调用存储过程小结 Java 调用存储过程是指在 Java 程序中调用数据库中的存储过程,以便实现复杂的业务逻辑和数据处理。存储过程是指保存在数据库并在数据库端执行的程序,可以使用特殊的语法在 Java 类中调用...
Java Swing是Java AWT(Abstract Window Toolkit)的扩展,提供了更为丰富的用户界面组件,使得开发者可以构建出功能强大且美观的图形用户界面。本篇将深入探讨Java Swing中的关键组件和设计模式,以及如何利用它们...
#### 四、小结 综上所述,通过合理的配置和编程技巧,利用JSP可以轻松实现首页的动态化。这不仅可以提高用户体验,还可以增强网站的功能性和可维护性。在实际开发中,还需要结合具体的技术栈和框架特性来进行优化和...
### 关于static的小结(Java内存溢出) #### 标题和描述中的知识点 在《关于static的小结(Java内存溢出)》这篇文章中,作者主要探讨了与Java中的`static`关键字相关的知识点,以及如何可能导致内存溢出的情况。...