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. [转]使用@Test 也可以从spring容器中获取依赖注入

    转自:http://blog.csdn.net/u010987379/article/details/52091790 @RunWith(SpringJUnit4ClassRunner.class) ...

  2. elasticsearch6.7 05. Document APIs(1)data replication model

    data replication model 本节首先简要介绍Elasticsearch的data replication model,然后详细描述以下CRUD api: 1.读写文档(Reading ...

  3. char和string的不同点

    'a'是char, "a"是char string,这两者都是普通的字符和字符串,和C中没什么不同 值得注意的是后者包含两个字符,末尾有一个隐身的'\0' 而:string str ...

  4. Django Rest Framework之权限

    基本代码结构 url.py: from django.conf.urls import url, include from app import views urlpatterns = [ url(r ...

  5. java enum使用方法

    直接上手吧,注释都写清楚了 编写枚举类 /** * 可以使用接口或类包裹枚举元素,使其可以统一调用入口 */ public interface TestEnumIntfc { /** * 创建枚举对象 ...

  6. 【转】巧用DOS tree命令+批处理 实现 指定文件 批量复制!

    转自:http://www.cnblogs.com/looky/archive/2010/01/24/1655292.html 今天一朋友叫我帮忙解决指定文件批量复制的问题,于是找了一大堆批处理命令, ...

  7. PL/SQL 查询的数据出现乱码

    解决方法: 1.首先在查询出Oracle数据库的字符集. select userenv('language') from dual; 2.新建系统变量 NLS_LANG,变量值为第一步查询出来的字符集 ...

  8. python中if else流程判断

    _username='Lily' _password=' username=input("username:") password=input("password:&qu ...

  9. mysqlclient and mysql-python安装出错方法

    Collecting mysql-python Using cached https://files.pythonhosted.org/packages/a5/e9/51b544da85a36a68d ...

  10. PHP类多继承的替代方案Traits

    概述 traits是PHP5.4新进入的特性,其目的就是解决PHP的类不能多继承的问题.Traits不是类!不能被实例化.可以理解为一组能被不同的类都能调用到的方法集合.只需要在类中使用关键词use引 ...