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. Best way to learn android and java?

    Question: I have been getting my feet wet with android sdk, eclipse, and other various beginner step ...

  2. IronPython初体验

    介绍 在 C# 程序中嵌入 IronPython 得到了很好的支持.在本教程中,我们将展示如何完成这个项目. 首先,我们将展示两个非常基本的例子,说明如何执行一个不导入任何模块的非常简单的脚本.然后, ...

  3. NIO学习笔记二

    Java NIO的通道channel 既可以从通道中读取数据,又可以写数据到通道.通道可以异步地读写.通道中的数据总是要先读到一个Buffer(缓冲区),或者总是要从一个Buffer(缓冲区)中写入. ...

  4. csharp: FTP Client Library using System.Net.FtpClient and FluentFTP,测试中存在的BUG修正

    https://netftp.codeplex.com/ /// <summary> /// Gets a file listing from the server. Each FtpLi ...

  5. window的Navigator 对象

    Navigator 对象包含有关浏览器的信息. Navigator 对象属性 document.write("浏览器的代码名:" + navigator.appCodeName + ...

  6. 【代码笔记】Web-HTML-图像

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  7. python自动化开发-9 进程 线程

    进程与线程 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一 ...

  8. Expo大作战(三十八)--expo sdk api之 FileSystem(文件操作系统)

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  9. Expo大作战(三十一)--expo sdk api之Payments(expo中的支付),翻译这篇文章傻逼了,完全不符合国内用户,我只负责翻译大家可以略过!

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  10. HBase中此类异常解决记录org.apache.hadoop.ipc.RemoteException(java.io.IOException):

    ERROR: Can't get master address from ZooKeeper; znode data == null   一定注意这只是问题的第一层表象,真的问题是: File /hb ...