三沣开发知识 购物 网址 游戏 小说 歌词 地图 快照 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 开发 租车 短信 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题
autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml
html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
  IT知识库 -> Java -> JVM -> 正文阅读
 

[Java]JVM

JVM 基本概念:类加载的过程大致分为三个阶段
1.加载阶段:本阶段主要把class的二进制代码加载进入JVM,并且进行常量池(类名,方法名,字段名),方法区(二进制字节码),栈(本地方法栈结构),堆(java.lang.class对象)的设置。
有三个加载类:Bootstrap ClassLoader,加载jre/lib/下的类;
Extension ClassLoader:加载jre/lib/ext下的类;
ApplicationClassLoader:加载classpath下的类(应用程序自己开发的类,如 工程目录/bin/下的.class文件)
还有一个扩展的加载类,满足应用程序的特殊需求。类的加载时,父亲loader优先执行load动作,父亲load不了时,子类运作。
2.链接阶段:又分为三个小阶段 校验,准备,解析。
校验:实施字节码文件的格式,语法等的校验。
准备:对静态变量申请存储空间,并设置默认的初始值。如:private static int a =2;那么在准备阶段a被设置为0;
解析:把方法区中的符号指针替换为直接引用。
3.初始化阶段:对静态变量进行初始化,执行静态块,创建类的实例。上述的a变量在初始化阶段会被设置为2。
第一步:验证静态变量和静态块的加载+链接(校验,准备,解析)+初始化过程中值的变化。
---------------------------------------------------------------------------------
 package com.chong.studyparalell.clazz.loader;
public class ClassLoaderDemo {
public static void main(String []args){
Test test2 = new Test();
System.out.println("Test2实例化结束"+test2.toString());
}
}
--------------------------------------------------------------------------------------
package com.chong.studyparalell.clazz.loader;
public class Test{
private static Test test1 = new Test();
private static int a = 2;
private static int b = 2;
static {
System.out.println("【Test类静态块】a=" + a);
}
public Test(){
System.out.println("【Test类构造方法】a=" + a);
System.out.println("【Test类构造方法】b=" + b);
System.out.println("【Test类实例】" + this.toString());
}
public static Test newInstance(){
return test1;
}
}
--------------------------------------------------------------------
log输出如下:
1 【Test类构造方法】a=0
2 【Test类构造方法】b=0
3 【Test类实例】com.chong.studyparalell.clazz.loader.Test@16c1857
4 【Test类静态块】a=2
5 【Test类构造方法】a=2
6 【Test类构造方法】b=2
7 【Test类实例】com.chong.studyparalell.clazz.loader.Test@1b1fd9c
8 Test2实例化结束com.chong.studyparalell.clazz.loader.Test@1b1fd9c
首先Test类在链接阶段(准备阶段),a,b分别被设置默认值0。
当new Test()执行后,
1)首先初始化Test类的三个静态变量 test1,a,b。
初始化test1时,第一次调用构造方法,此时a,b为0。对应日志1,2行。
实例化test1,日志第3行。
test1初始化完成后,继续初始化a,b,设为2。
接着初始化静态块 ,对应日志第4行。
2)执行Test类的构造方法
因为a,b已经被初始化为2,所以执行类的构造方法时,会输出a,b 为2。日志第5,6行。
实例化后输出地址信息,日志第7行。
3)最终main方法里打出实例工作完成,日志第8行。
 -------------------------------------------------------------
 第二步,加入父类后,进行确认。
-------------------------------------------------------------
package com.chong.studyparalell.clazz.loader;
public class TestBase {
private static int base_a = 2;
private static int base_b = 2;
static {
System.out.println("【父类静态块】 base_a="+base_a);
}
public TestBase(){
System.out.println("【父类 构造方法】base_a=" + base_a);
System.out.println("【父类 构造方法】base_b=" + base_b);
System.out.println("【父类 实例】"+ this.toString());
}
}
------------------------------------------------------------------
package com.chong.studyparalell.clazz.loader;
public class Test extends TestBase{
内容同第一步;
}
------------------------------------------------------------------
log输出如下:
 【父类静态块】 base_a=2
【父类 构造方法】base_a=2
【父类 构造方法】base_b=2
【父类 实例】com.chong.studyparalell.clazz.loader.Test@19ab8d
【Test类构造方法】a=0
【Test类构造方法】b=0
【Test类实例】com.chong.studyparalell.clazz.loader.Test@19ab8d
【Test类静态块】a=2
【父类 构造方法】base_a=2
【父类 构造方法】base_b=2
【父类 实例】com.chong.studyparalell.clazz.loader.Test@14dcfad
【Test类构造方法】a=2
【Test类构造方法】b=2
【Test类实例】com.chong.studyparalell.clazz.loader.Test@14dcfad
Test2实例化结束com.chong.studyparalell.clazz.loader.Test@14dcfad
可以发现父类的静态变量,静态块,构造方法首先被初始化。然后子类的静态变量,静态块和构造方法被初始化。
------------------------------------------------------------------
第三步:写一个自定义的类加载器
------------------------------------------------------------------
 package com.chong.studyparalell.clazz.loader;
public class MyClassLoaderPilot {
public static void main(String[] args) {
try {
MyClassLoader classLoader = new MyClassLoader();
String filename = "com.chong.studyparalell.demon.DemonThreadDemo";
Object clazz = classLoader.loadCustomizeClass(filename);
System.out.println(clazz);
} catch (Exception e) {
e.printStackTrace();
}
}
}
------------------------------------------------------------------
package com.chong.studyparalell.clazz.loader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MyClassLoader extends ClassLoader {
private String demoPath = "D:\\work\\temp\\";
public Class<?> loadCustomizeClass(String filename) throws ClassNotFoundException {
FileInputStream fis = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
// 1.获取class文件的字节码(二进制数据)
String[] fileNames = filename.split("\\.");
fis = new FileInputStream(demoPath + fileNames[fileNames.length-1] +".class");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
baos.write(bytes, 0, len);
}
} catch (Exception e) {
throw new ClassNotFoundException();
} finally {
try {
fis.close();
} catch (IOException e) {
throw new ClassNotFoundException();
}
}
byte[] paramArrayOfByte = baos.toByteArray();
// 2。把二进制文件定义为class对象返回
return defineClass(filename, paramArrayOfByte, 0, paramArrayOfByte.length);
}
}
------------------------------------------------------------------
日志输出如下:
class com.chong.studyparalell.demon.DemonThreadDemo
------------------------------------------------------------------
实际的跟着代码走一遍,看看控制台的输出,用自己的思路虚拟着跟一跟,对于类的加载过程能够认识的更加清晰一些。
参看link:
http://www.cnblogs.com/ityouknow/p/5603287.html
http://www.cnblogs.com/xiaoxiaohui2015/p/5838674.html
  Java 最新文章
三个目前比较常见的连接池的简单运用
Shiro:授权控制
初学者易上手的SSH
【基于初学者的SSH】struts2 的拦截器、令牌
初学者易上手的SSH
MyEclipse快捷键大全(绝对全)
ssm项目,web容器无法初始化项目
Mybatis的原理
tomcat源码学习(2)  关于apache&
eclipse报错:Failed to load the JNI shar
上一篇文章      下一篇文章      查看所有文章
加:2017-10-12 23:22:36  更:2017-10-12 23:23:03 
 
技术频道: 站长资讯 .NET新手区 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA Visual Studio ASP.NET MVC .NET控件开发 Entity Framework WinRT/Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动设计 Html/Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP Oracle ERP Dynamics CRM K2 BPM 信息安全 企业信息化其他 Android开发 iOS开发 Windows Phone Windows Mobile 其他手机开发 敏捷开发 项目与团队管理 软件工程其他 SQL Server Oracle MySQL NoSQL 其它数据库 Windows 7 Windows Server Linux
脚本语言: vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程
网站开发: CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2017年10日历
2017-10-22 7:15:25
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库