运行前先编译成class,类初始化的时候调用java.lang.ClassLoader
加载字节码,ClassLoader调用JVM的native方法来定义一个java.lang.Class
实例
- 启动类加载器: 将
/lib
下目录下的类加载到虚拟机内存中,加载java的核心库,不继承java.lang.ClassLoader
,不能被java程序调用,是使用c++编写的
- 拓展类加载器:加载
/lib/ext
下的,拓展库,可以直接使用
- 应用程序类加载器:一般情况下是系统默认的类加载器
层次结构大概如下
Bootstrap ClassLoader
Extension ClassLoader
App ClassLoader
默认使用第三个,ClassLoader.getSystemClassLoader()
返回的是第三个
获取类加载器的时候如果返回null,那么就是被Bootstrap加载的
核心方法
- loadClass 加载指定类
- findClass 查找指定类
- findLoadedClass 查找JVM已经加载过的类
- defineClass 定义一个类
- resolveClass 链接指定的类
类加载方式
- 显式 :java反射或ClassLoader(动态加载)
- 隐式 : 类名.方法名(),或者new
Class.forName("xx")
会初始化静态属性和方法,有恶意代码就会执行了
ClassLoader.loadClass
不会初始化类方法
常看常新
package tmp;
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths;
public class MyClassLoader extends ClassLoader{ public static String className = "tmp.EvilObject"; public static Path path = Paths.get("/Users/dionysus/code/IdeaProjects/Serial/src/main/java/tmp/EvilObject.class"); public static byte[] classBytes;
static { try { classBytes = Files.readAllBytes(path); } catch (IOException e) { throw new RuntimeException(e); } }
protected Class<?> findClass(String name) throws ClassNotFoundException { System.out.println(name); if (className.equals(name)) { return defineClass(className, classBytes, 0, classBytes.length); } return super.findClass(name); }
public static void main(String[] args) throws Exception{ MyClassLoader myClassLoader = new MyClassLoader(); Class<?> aClass = myClassLoader.loadClass(className); Object a = aClass.newInstance(); } }
|
恶意类
package tmp;
import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; import java.io.IOException; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.Hashtable;
public class EvilObject extends UnicastRemoteObject implements ObjectFactory { static { try { Runtime.getRuntime().exec("open -a Calculator"); } catch (IOException e) { e.printStackTrace(); } }
protected EvilObject() throws RemoteException { }
public static void main(String[] args) throws Exception { new EvilObject(); }
@Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception { return null; } }
|