标签:cas 应用程序 产生 检查 位置 指针 有一个 技术 根据
类加载检查 ===> 分配内存 ===> 初始化零值 ===> 设置对象头 ===> 执行init方法
虚拟机遇到一条new指令时,首先检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,就必须执行相应的类加载过程。
在类加载检查通过后,虚拟机将为新生对象分配内存。
对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。分配方式包括指针碰撞和空闲列表。选择哪种方式取决于Java堆是否规整,Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
内存分配的并发问题,虚拟机采用两种方式来保证线程安全。
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),保证对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
初始化零值之后需要对对象头进行必要的设置。
上面工作完成后,在虚拟机的视角,新的对象已经产生。从Java程序的视角,执行new指令后就会执行init方法,把对象按照程序员的医院进行初始化,从而得到一个真正可用的对象。
①使用句柄:在Java堆中创建句柄池,句柄包含对象实例数据和对象类型数据,本地变量表中的reference存储对象的句柄地址。
②直接指针:本地变量表中存储的直接就是对象的地址。
直接指针速度快,而使用句柄的最大好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。
类加载过程:加载、连接、初始化
类的生命周期:加载、连接、初始化、使用、卸载
实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。
JVM中内置了三个重要的ClassLoader,除了BootstrapClassLoader,其它类加载器均由Java实现且全部继承自java.lang.ClassLoader。
每一个类都有一个对于它的类加载器。系统中的ClassLoader在协同工作时会默认使用双亲委派机制。
在类加载的时候,首先判断该类是否被加载,已经加载过的类无需加载会直接返回,负责会自己尝试加载。加载的时候,首先会把该请求委派给父类加载器进行处理,因此所有的请求最终都会传送到顶层的启动类加载BootstrapClassLoader加载器中。当父类加载加载器无法处理时,才会自己进行处理。当父类加载器为null时,会使用BootstrapClassLoader作为父类加载器。
JDBC:使用线程上下文类加载器(Thread Context ClassLoader)
JDBC的Driver接口定义在JDK中,其实现由数据库的服务商来提供,比如MySQL驱动包。DriverManager 类中要加载各个实现了Driver接口的类,然后进行管理,其由BootstrapClassLoader加载,而其Driver接口的实现类是位于服务商提供的 Jar 包,根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。也就是说BootstrapClassLoader还要去加载jar包中的Driver接口的实现类。然而BootstrapClassLoader默认只负责加载 $JAVA_HOME中jre/lib/rt.jar 里所有的类,所以需要由子类加载器去加载Driver实现,这就破坏了双亲委派模型。
Tomcat:自定义类加载器,Tomcat的类加载器如下图。
每个Tomcat的WebappClassLoader加载自己目录下的class文件,不会传递给父类加载器,破坏了双亲委派机制。
Tomcat自定义了很多来加载器,可能处于以下目的:
webapp
中的 class
和 lib
,需要相互隔离,不能出现一个应用中加载的类库会影响另一个应用的情况,而对于许多应用,需要有共享的lib以便不浪费资源;JVM
一样的安全性问题。使用单独的 ClassLoader
去装载 Tomcat
自身的类库,以免其他恶意或无意的破坏;标签:cas 应用程序 产生 检查 位置 指针 有一个 技术 根据
原文地址:https://www.cnblogs.com/chiaki/p/13488293.html