package com.lsw.classloader;

import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

class Parent{
public static int a=3;
public int b = 4;
static {
System.out.println("Parent static block");
}
}
class MyClassLoader extends ClassLoader {
private String name = ""; //类加载器的名字
private String path = "";

public MyClassLoader(String name) {
super(); //让系统类加载器成为该类的父加载器
this.name = name;
}
public MyClassLoader(ClassLoader parent,String name){
super(parent); //显示指定该类加载器的父加载器
this.name = name;
}

private byte[] loadByte(String name) throws Exception {

String[] names = name.split("\\.");

FileInputStream fis = new FileInputStream(path + names[3] + ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;

}

protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException{
//初始化流程 1.给类的静态变量赋默认值 a=0 执行静态代码块
// 2.给静态变量赋初始值a=3
System.out.println(Parent.a);
//static方法没有this的方法,在static方法内部不能调用非静态方法,反过来可以
//而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法,这实际上是static方法的主要用途
//静态变量和非静态变量的区别:静态变量被所有对象共享,在内存这种只有一个副本,在类初次加载的时候初始化。非静态变量是对象拥有,在对象创建的时候被初始化,存在多个副本
/*System.out.println(Parent.b); 这种写法可以,因为类没有创建*/
//连续创建两个Parent对象,静态代码块还是执行一次。说明静态代码块已在内存区域存在(存储在哪里?堆、栈)
System.out.println(new Parent().b);
System.out.println(new Parent().b);
System.out.println("***********************");
//java.lang.String 由根加载器进行加载 bootstrap
Class clazz = Class.forName("java.lang.String");
System.out.println(clazz.getClassLoader()); //结果为null
//系统加载器或应用加载器加载
clazz = Class.forName("com.lsw.classloader.Parent");
System.out.println(clazz.getClassLoader());

System.out.println("********自定义类的加载***********");
//应用类加载器 调用默认的构造方法 默认的构造函数父类加载器是应用类加载器
//父类是系统类加载器 ->扩展类加载器->根类加载器
MyClassLoader loader1 = new MyClassLoader("loader1");
loader1.setPath("E:\\tools\\1\\");
//父类加载器是loader1
MyClassLoader loader2 = new MyClassLoader(loader1,"loader2");
loader2.setPath("E:\\tools\\2\\");
//父类加载器是bootstrap
MyClassLoader loader3 = new MyClassLoader(null,"loader3");
loader3.setPath("E:\\tools\\3\\");
//加载路径解析
//bootstrap 加载路径从系统属性sun.boot.class.path所指定的目录中加载类库
//extension jre/lib/ext或者从系统属性java.ext.dirs
//system 从环境变量 classpath或者系统属性java.class.path
test(loader1);
//loader2 加载流程 1.首先委托loader1进行加载 2.loader1发现还有父类-系统类加载器 委托系统类加载器加载
//3. 系统类依次查找 扩展类加载器加载 根类加载器加载
//4. 根类加载器没有查找到类,扩展类加载查找,系统类查找,loader1查找到了,loader1进行加载
//被加载的加载器被称为定义类加载器 所有的加载器可以称为初始类加载器
test(loader2);
test(loader3);

//解析:loader1和loader3在各自的命名空间之中都存在sample类和dog类
//堆区 方法区
//load1
//代表sample类的class实例 sample来着tools\1
//代表dog类的class实例 dog来着tools\1
//load3
//代表sample类的class实例 sample来着tools\3
//代表dog类的class实例 dog来着tools\3

System.out.println(loader2.getParent());
ClassLoader loader = ClassLoader.getSystemClassLoader();
while(loader !=null){
loader = loader.getParent();
System.out.println(loader);
}
//由于根类加载器是C/C++编写的 所以打印不出任何东西

//反射
System.out.println("-----------------------");
//cls 引用变量 引用的是堆区的myclassloader对象
Class cls = loader1.loadClass("com.lsw.classloader.Sample");
//object 引用变量 引用的是堆区的sample类的class对象 指向方法区内的sample二进制数据结构
Object object = cls.newInstance(); //创建一个sample类的对象
System.out.println(object);
//field 引用变量 引用的是堆区的sample对象
Field field = object.getClass().getField("v1");
// field = cls.getField("v1");
int i = field.getInt(object); //the object to extract the int value from
System.out.println(i);

}
public static void test(ClassLoader loader) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
Class clazz2 = loader.loadClass("com.lsw.classloader.Sample");
Object obj = clazz2.newInstance();
}
}

JVM实践的更多相关文章

  1. JVM - 堆外内存

    看了不少资料,总结下: 堆外内存 / 直接内存(Direct Memory)JDK1.4中引入的NIO类,基于channel和Buffer的I/O方式,可用Native库直接分配堆外内存,然后利用一个 ...

  2. [转帖]支撑双11每秒17.5万单事务 阿里巴巴对JVM都做了些什么?

    支撑双11每秒17.5万单事务 阿里巴巴对JVM都做了些什么? https://mp.weixin.qq.com/s?__biz=MzA3OTg5NjcyMg==&mid=2661671930 ...

  3. 五分钟学Java:如何学习Java面试必考的JVM虚拟机

    原创声明 本文首发于微信公众号[程序员黄小斜] 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 为什么要学习JVM虚拟机 最近的你有没有参加Java面试呢?你有没有发现,Java ...

  4. java jvm学习笔记五(实践自己写的类装载器)

     欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和 ...

  5. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  6. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

  7. 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载

    <深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...

  8. JVM性能参数调优实践,不会执行Full GC,网站无停滞

    原文来自:http://bbs.csdn.net/topics/310110257 本文只做整理记录,供个人学习. 1 JVM参数调优是个很头痛的问题,设置的不好,JVM不断执行Full GC,导致整 ...

  9. 《深入理解Java虚拟机:JVM高级特性与最佳实践》读书笔记

    第一部分 走进Java 一.走进Java 1.概述 java广泛应用于嵌入式系统.移动终端.企业服务器.大型机等各种场合,摆脱了硬件平台的束缚,实现了“一次编写,到处运行”的理想 2.java技术体系 ...

随机推荐

  1. 服务器端事件发送SSE

    背景 近期有这么一个需求: 手机端需要展示一个比较大的pdf 基于手机端网络/流量/体验等考虑,希望不通过pdf下载然后展示 而是把pdf转成一张张的图片,然后再在手机上展示. 分析 pdf转图片,肯 ...

  2. java-两个整数变量的交换-不需要定义第三方变量

    代码如下: class Example { public static void main(String[] args) { /* * 位异或运算符的特点 * ^的特点:一个数据对另一个数据位异或两次 ...

  3. Hash table lengths and prime numbers

    Website:http://srinvis.blogspot.ca/2006/07/hash-table-lengths-and-prime-numbers.html This has been b ...

  4. linux最靠谱安装python3

    linux环境编译安装python3, 最靠谱的安装方法了这个 1. 下载编译安装python的依赖软件包,只需要执行即可 yum install gcc patch libffi-devel pyt ...

  5. jQuery动画切换引擎插件Velocity.js

    Velocity.js 官网 Velocity.js实现弹出式相框 慕课网 极棒的jquery动画切换引擎插件Velocity.js jQ库 (function($){ // 普通调用 /*$('#d ...

  6. c语言学习笔记-switch

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一.switch函数意义 选择性执行 二.switch函数结构 switch(表达式) { case: 常量表达式; 语句1; ...

  7. 安装Vue和创建一个Vue脚手架项目

    首先 安装node.js,安装成功可以在控制台输入[node --version ]查看node的版本,因为安装了node会自带npm所以我们可以用 [npm --version]查到npm版本  如 ...

  8. openlayer3之高级标注实现

    首先看实现效果: 实现要点: 1)树形标注实现 2)复杂标注样式定义 3)效率优化 1.树形标注实现 树形标注采用字体符号来实现,包括以下几个步骤 1)载入字体 2)设置标注值与字体对照关系 3)设置 ...

  9. loadrunner 脚本开发-文件读写操作

    脚本开发-文件读写操作 by:授客 QQ:1033553122 函数说明 函数原型: size_t fwrite( const void *buffer, size_t size, size_t co ...

  10. 查看neighbors大小对K近邻分类算法预测准确度和泛化能力的影响

    代码: # -*- coding: utf-8 -*- """ Created on Thu Jul 12 09:36:49 2018 @author: zhen &qu ...