类加载全过程
package com.bjsxt.test;
public class Demo01 {
static{
System.out.println("静态初始化Demo01");
}
public static void main(String[] args) throws Exception {
System.out.println("Demo01的main方法!");
System.out.println(System.getProperty("java.class.path"));
//主动引用
// new A();
// System.out.println(A.width);
// Class.forName("com.bjsxt.test.A");
//被动引用
// System.out.println(A.MAX);
// A[] as = new A[10];
System.out.println(B.width);
}
}
class B extends A {
static {
System.out.println("静态初始化B");
}
}
class A extends A_Father {
public static int width=100; //静态变量,静态域 field
public static final int MAX=100;
static {
System.out.println("静态初始化类A");
width=300;
}
public A(){
System.out.println("创建A类的对象");
}
}
class A_Father extends Object {
static {
System.out.println("静态初始化A_Father");
}
}
深入类加载器
package com.bjsxt.test;
/**
* 测试类加载器的层次结构、双亲委托机制
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class Demo02 {
public static void main(String[] args) {
System.out.println(ClassLoader.getSystemClassLoader()); //目前使用的类加载器
System.out.println(ClassLoader.getSystemClassLoader().getParent());
System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent()); //JAVA_HOME/jre/lib/rt.jar
System.out.println(System.getProperty("java.class.path"));//目前使用的类加载器的工作路径
System.out.println("################");
String a = "gaogao";
System.out.println(a.getClass().getClassLoader());
System.out.println(a);
}
}
package com.bjsxt.test;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 自定义文件系统类加载器
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class FileSystemClassLoader extends ClassLoader {
//com.bjsxt.test.User --> d:/myjava/ com/bjsxt/test/User.class
private String rootDir;
public FileSystemClassLoader(String rootDir){
this.rootDir = rootDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name);
//应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类。
if(c!=null){
return c;
}else{
ClassLoader parent = this.getParent();
try {
c = parent.loadClass(name); //委派给父类加载
} catch (Exception e) {
// e.printStackTrace();
}
if(c!=null){
return c;
}else{
byte[] classData = getClassData(name);
if(classData==null){
throw new ClassNotFoundException();
}else{
c = defineClass(name, classData, 0,classData.length);
}
}
}
return c;
}
private byte[] getClassData(String classname){ //com.bjsxt.test.User d:/myjava/ com/bjsxt/test/User.class
String path = rootDir +"/"+ classname.replace('.', '/')+".class";
// IOUtils,可以使用它将流中的数据转成字节数组
InputStream is = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
is = new FileInputStream(path);
byte[] buffer = new byte[1024];
int temp=0;
while((temp=is.read(buffer))!=-1){
baos.write(buffer, 0, temp);
}
return baos.toByteArray();
}catch(Exception e){
e.printStackTrace();
return null;
}finally{
try {
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(baos!=null){
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.bjsxt.test;
/**
* 测试自定义的FileSystemClassLoader
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class Demo03 {
public static void main(String[] args) throws Exception{
FileSystemClassLoader loader = new FileSystemClassLoader("d:/myjava"); //d:/myjava下java文件需要调用cmd进行编译(见上)。
FileSystemClassLoader loader2 = new FileSystemClassLoader("d:/myjava");
Class<?> c = loader.loadClass("com.bjsxt.gaoqi.HelloWorld");
Class<?> c2 = loader.loadClass("com.bjsxt.gaoqi.HelloWorld");
Class<?> c3 = loader2.loadClass("com.bjsxt.gaoqi.HelloWorld");
Class<?> c4 = loader2.loadClass("java.lang.String");
Class<?> c5 = loader2.loadClass("com.bjsxt.test.Demo01");
System.out.println(c.hashCode());
System.out.println(c2.hashCode()); //c和c2是相同的类
System.out.println(c3.hashCode()); //同一个类,被不同的加载器加载,JVM认为也是不相同的类
System.out.println(c4.hashCode());
System.out.println(c4.getClassLoader()); //引导类加载器
System.out.println(c3.getClassLoader()); //自定义的类加载器
System.out.println(c5.getClassLoader()); //系统默认的类加载器
}
}
package com.bjsxt.test;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
/**
* 网络类加载器
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class NetClassLoader extends ClassLoader {
//com.bjsxt.test.User --> www.sxt.cn/myjava/ com/bjsxt/test/User.class
private String rootUrl;
public NetClassLoader(String rootUrl){
this.rootUrl = rootUrl;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name);
//应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类。
if(c!=null){
return c;
}else{
ClassLoader parent = this.getParent();
try {
c = parent.loadClass(name); //委派给父类加载
} catch (Exception e) {
// e.printStackTrace();
}
if(c!=null){
return c;
}else{
byte[] classData = getClassData(name);
if(classData==null){
throw new ClassNotFoundException();
}else{
c = defineClass(name, classData, 0,classData.length);
}
}
}
return c;
}
private byte[] getClassData(String classname){ //com.bjsxt.test.User d:/myjava/ com/bjsxt/test/User.class
String path = rootUrl +"/"+ classname.replace('.', '/')+".class";
// IOUtils,可以使用它将流中的数据转成字节数组
InputStream is = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
URL url = new URL(path);
is = url.openStream();
byte[] buffer = new byte[1024];
int temp=0;
while((temp=is.read(buffer))!=-1){
baos.write(buffer, 0, temp);
}
return baos.toByteArray();
}catch(Exception e){
e.printStackTrace();
return null;
}finally{
try {
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(baos!=null){
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
自定加密解密类加载器:
package com.bjsxt.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 加密工具类
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class EncrptUtil {
public static void main(String[] args) {
encrpt("d:/myjava/HelloWorld.class", "d:/myjava/temp/HelloWorld.class");//把d:/myjava/HelloWorld.class加密到d:/myjava/temp/HelloWorld.class。
}
public static void encrpt(String src, String dest){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(src);
fos = new FileOutputStream(dest);
int temp = -1;
while((temp=fis.read())!=-1){
fos.write(temp^0xff); //取反操作
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.bjsxt.test;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 加载文件系统中加密后的class字节码的类加载器
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class DecrptClassLoader extends ClassLoader {
//com.bjsxt.test.User --> d:/myjava/ com/bjsxt/test/User.class
private String rootDir;
public DecrptClassLoader(String rootDir){
this.rootDir = rootDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name);
//应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类。
if(c!=null){
return c;
}else{
ClassLoader parent = this.getParent();
try {
c = parent.loadClass(name); //委派给父类加载
} catch (Exception e) {
// e.printStackTrace();
}
if(c!=null){
return c;
}else{
byte[] classData = getClassData(name);
if(classData==null){
throw new ClassNotFoundException();
}else{
c = defineClass(name, classData, 0,classData.length);
}
}
}
return c;
}
private byte[] getClassData(String classname){ //com.bjsxt.test.User d:/myjava/ com/bjsxt/test/User.class
String path = rootDir +"/"+ classname.replace('.', '/')+".class";
// IOUtils,可以使用它将流中的数据转成字节数组
InputStream is = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
is = new FileInputStream(path);
int temp = -1;
while((temp=is.read())!=-1){
baos.write(temp^0xff); //取反操作,相当于解密
}
return baos.toByteArray();
}catch(Exception e){
e.printStackTrace();
return null;
}finally{
try {
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(baos!=null){
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.bjsxt.test;
/**
* 测试简单加密解密(取反)操作
* @author 尚学堂高淇 www.sxt.cn
*
*/
public class Demo04 {
public static void main(String[] args) throws Exception {
//测试取反操作
// int a = 3; //0000011
// System.out.println(Integer.toBinaryString(a^0xff)); ff是11111111,取异或
//加密后的class文件,正常的类加载器无法加载,报classFormatError
// FileSystemClassLoader loader = new FileSystemClassLoader("d:/myjava/temp");//此文件加密
// Class<?> c = loader.loadClass("HelloWorld");
// System.out.println(c);
DecrptClassLoader loader = new DecrptClassLoader("d:/myjava/temp");
Class<?> c = loader.loadClass("HelloWorld");
System.out.println(c);
}
}
线程上下文类加载器_web服务器类加载机制_OSGI技术模块开发原理介绍 (略)