javassist动态生成class

2023-10-30

 

什么是javassist?

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。
关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类
 

联想

 由上可知,javassist 可以用来动态生成class文件,并且JVM可以直接加载生成的class文件。

具体作用:

设计一个对接系统,通过动态模型的增删改触发业务系统相应服务的调用。模型增删改方法动态发布为WebService服务。WebService服务采用CXF发布,动态类生成采用Javassist。由于WebService服务类需要添加WebService相关注解。

实战演练

从0开始实战,首先我们认识最初级的由javassist生成class类并且修改保存
package com.bsoft.javassis;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;


import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

public class TestJavassis {

	/**
	 * @param args
	 * @author yuzg
	 * update time 2017-06-20
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/**
		 * ClassPool是缓存CtClass对象的容器,所有的CtClass对象都在ClassPool中。
		 * 所以,CtClass对象很多时,ClassPool会消耗很大的内存,为了避免内存的消耗
		 * ,创建ClassPool对象时可以使用单例模式,
		 * 或者对于CtClass对象,调用detach方法将其从ClassPool中移除
		 * 在ClassPool源码中getDefault 是单例模式生成
		 * 
		 *  public static synchronized ClassPool getDefault() {
        if (defaultPool == null) {
            defaultPool = new ClassPool(null);
            defaultPool.appendSystemPath();
        }

        return defaultPool;
    }
		 */
		ClassPool classpool =ClassPool.getDefault();
		//创建类名
		CtClass ctClass = classpool.makeClass("com.bsoft.esb.IEsbInvoker1");
//		ctClass.stopPruning(true);
		try {
			//添加属性
	        ctClass.addField(CtField.make("private int age;", ctClass));
	        //添加setAge方法
	        ctClass.addMethod(CtMethod.make("public void setAge(int age){this.age = age;}", ctClass));
	        ctClass.addMethod(CtMethod.make("public int getAge(){return this.age;}", ctClass));
			byte[] byteArray = ctClass.toBytecode();
	        FileOutputStream output = new FileOutputStream("D:\\IEsbInvoker1.class");
	        output.write(byteArray);                                        
	        output.close();
	        
			/***
			 * 如果下面的判断和解冻方法不加会报错 
			 * java.lang.RuntimeException: com.bsoft.esb.IEsbInvoker1 class is frozen
			 * 原因解释如下:
			 *  当CtClass对象通过writeFile()、toClass()、toBytecode()转化为Class后,
			 *  Javassist冻结了CtClass对象,因此,JVM不允许再次加载Class文件,所以不允许对其修改。
			 */
	        if(ctClass.isFrozen()){
				ctClass.defrost();
			}
			 ctClass = classpool.get("com.bsoft.esb.IEsbInvoker1");
			System.out.println(ctClass);
			CtField param = new CtField(classpool.get("java.lang.String"), "name", ctClass);  
			 ctClass.addField(CtField.make("private java.lang.String sex;", ctClass));
		     ctClass.addField(CtField.make("private java.lang.String name;", ctClass));
		     ctClass.addMethod(CtNewMethod.setter("setName", param));  
		     ctClass.addMethod(CtNewMethod.getter("getName", param));  
//		     // 添加无参的构造体  
//	        CtConstructor cons = new CtConstructor(new CtClass[] {}, ctClass);  
//	        cons.setBody("{name = \"Brant\";}");  
//	        ctClass.addConstructor(cons);  
	     // 添加有参的构造体  
		    CtConstructor   cons = new CtConstructor(new CtClass[] {classpool.get("java.lang.String")}, ctClass);  
	        cons.setBody("{$0.name = $1;}");  
	        ctClass.addConstructor(cons);  
		    byteArray = ctClass.toBytecode();
	        output = new FileOutputStream("D:\\IEsbInvoker1.class");
	        output.write(byteArray);
	        output.close();

	        //ctClass转class后创建对象
	        Object o =ctClass.toClass().newInstance();
	        //这样写会报错:java.lang.ClassNotFoundException: com.bsoft.esb.IEsbInvoker1
	        /***
	         * 此时应该还在pool中
	         */
//	        Class.forName("com.bsoft.esb.IEsbInvoker1").newInstance();
	        //获取方法
	        Method methodSet = o.getClass().getMethod("setName", new Class[] {String.class});
	       //反射原理
	        methodSet.invoke(o, "Alen");
	        
	        Method getter = o.getClass().getMethod("getName");
	        System.out.println("name:"+getter.invoke(o, null));
		} catch (NotFoundException e) {
			System.out.println(e.getMessage());
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (CannotCompileException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}


$0, $1, $2, ...  代表的含义:

 $ 0代表的是 this,$ 1代表方法参数的第一个参数、$ 2代表方法参数的第二个参数,以此类推,$N代表是方法参数的第N个。例如:  
setName(String Name){
   $0.name=$1;
}
相当于 this.name=Name;

分别查看两次保存文件前后的class 文件 可用debug断点
首次保存生成的class文件:
package com.bsoft.esb;

public class IEsbInvoker1
{
  private int age;

  public void setAge(int paramInt)
  {
    this.age = paramInt;
  }

  public int getAge()
  {
    return this.age;
  }
}
修改后:
输出:
name:Alen
一个class 文件就生成好了。并且通过java反射机制可以明显看出,和jvm主动调用class类中的方法并无两样。稍后上传jar包资源文件
javassist.jar下载路径: 点击下载javassist
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

javassist动态生成class 的相关文章

  • Keytool 应用程序在哪里?

    我需要在android中使用mapview控件 但我似乎不明白如何运行keytool 是用eclipse安装的吗 我好像找不到下载链接 Thanks keytool http docs oracle com javase 7 docs te
  • 无法在 Android 10 中创建目录

    我无法在 android 10 中创建目录 它可以在 android Oreo 之前的设备上运行 我尝试了两种创建文件夹的方法 Using File mkdir File f new File Environment getExternal
  • 未找到 MessageSource 的 ResourceBundle [消息]:找不到基本名称消息的包

    在 applicationContext xml 中 我定义了 MessageSource 如下所示
  • 无法解析类型为 xxx 的任何 bean;限定符:[@javax.enterprise.inject.Any()]

    我有一个 LoginProvider 接口 public interface LoginProvider boolean login String username String password 以及两种不同的实现 public clas
  • 使用 GWT CellTableBuilder 构建树表

    Is it possible to build a tree table like this http www sencha com examples ExamplePlace basictreegrid with the new Cell
  • 如果在睡眠线程上调用interrupt()会发生什么?

    我有一个线程 然后run I call sleep 如果我中断这个线程会发生什么 MyThread extends Thread public void run try sleep 1000000 catch InterruptedExce
  • Grails 2.3.0 自动重新加载不起作用

    我最近将我们的项目升级到 grails 2 3 0 一切工作正常 除了每当我更改代码时自动重新加载都无法工作的问题 这包括所有项目工件 控制器 域 服务 gsps css 和 javascript 文件 我的旧版本 grails 可以正常工
  • 无法使用maven编译java项目

    我正在尝试在 java 16 0 1 上使用 maven 构建 IntelliJ 项目 但它无法编译我的项目 尽管 IntelliJ 能够成功完成 在此之前 我使用maven编译了一个java 15项目 但我决定将所有内容更新到16 0 1
  • 来自数据库的 jfreechart 散点图

    如何使用java中的jfreechart绘制mysql数据库表中数据的散点图 我使用过 Swing 库 任何链接都会有帮助 我搜索了谷歌但找不到理解的解决方案 如果您有代码 请提供给我 实际上我确实做了条形图并使用 jfreechart 绘
  • eclipse中导入项目文件夹图标

    我在 Eclipse 工作区中新导入的 Maven 项目有J and M项目文件夹顶部的图标 项目和包资源管理器 而其他导入的 Maven 项目只有一个J icon 有人可以解释其中的区别吗 该项目有J装饰器被称为 Java 项目和具有M装
  • 如何在 JSP 中导入类?

    我是一个完全的JSP初学者 我正在尝试使用java util List在 JSP 页面中 我需要做什么才能使用除以下类之外的类java lang 使用以下导入语句进行导入java util List 顺便说一句 要导入多个类 请使用以下格式
  • 使用 RecyclerView 适配器在运行时更改布局屏幕

    我有两个布局文件 如下所示 如果列表中存在数据 则我显示此布局 当列表为空时 我会显示此布局 现在我想在运行时更改布局 当用户从列表中删除最后一项时 我想将布局更改为第二张图片中显示的 空购物车布局 In getItemCount Recy
  • 记录骆驼路线

    我的项目中有几个 Camel 上下文 如果可能的话 我想以逆向工程方式记录路线 因为我们希望保持与上下文相关的文档最新 最好的方法是什么 我们倾向于预先实际设计路线 并使用来自EIP book http www eaipatterns co
  • 内存一致性 - Java 中的happens-before关系[重复]

    这个问题在这里已经有答案了 在阅读有关内存一致性错误的 Java 文档时 我发现与创建 发生 之前 关系的两个操作相关的点 当语句调用时Thread start 每个具有 与该语句发生之前的关系也有一个 与 new 执行的每个语句之间发生的
  • 如何从 Retrofit2 获取字符串响应?

    我正在做 android 正在寻找一种方法来执行超级基本的 http GET POST 请求 我不断收到错误 java lang IllegalArgumentException Unable to create converter for
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • Android Studio 将音乐文件读取为文本文件,如何恢复它?

    gameAlert mp3是我的声音文件 运行应用程序时 它询问我该文件不与任何文件类型关联 请定义关联 我选择TextFile错误地 现在我的音乐文件被读取为文本文件 我如何将其转换回music file protected void o
  • JSON 到 hashmap (杰克逊)

    我想将 JSON 转换为 HashMapJackson http jackson codehaus org 这是我的 JSON String json Opleidingen name Bijz trajecten zorg en welz
  • Hibernate 和可序列化实体

    有谁知道是否有一个框架能够从实体类中剥离 Hibernate 集合以使它们可序列化 我查看了 BeanLib 但它似乎只进行实体的深层复制 而不允许我为实体类中的集合类型指定实现映射 BeanLib 目前不适用于 Hibernate 3 5
  • 启动Java项目时发生类冲突:ClassMetadataReadingVisitor将接口org.springframework.asm.ClassVisitor作为超类

    我正在使用最新的Spring框架版本 3 2 2 RELEASE 开发一个Java Web项目 但是现在项目启动时遇到了问题 详细错误是 java lang IncompleteClassChangeError 类 org springfr

随机推荐

  • Linux文件权限分段说明

    Linux文件权限分段说明 Linux中的文件属性权限描述一共10位长度 并分为四段 如 rwxrwx 一共十位 第一段占一位 代表文件类型 其中例子中的 代表普通文件 其余的表示还有 文件类型部分 文件 d 文件夹 l 链接文件 可以理解
  • nginx解析PHP特卡,nginx解析PHP程序报错的解决方案

    root server 2 log tail f nginx error log 2019 07 31 01 51 02 error 26151 0 52 FastCGI sent in stderr Primary script unkn
  • Springboot 文件处理导入导出

    简单记录下使用Springboot进行文件与后端交互 excel前台导出等内容 这里用到了 elelemt ui HTML vue Springboot框架 一 后台导入 HTML
  • VBS加载微软网页控件webview2(Edge-Chromium谷歌内核)

    VBS加载微软网页控件webview2 Edge Chromium谷歌内核 VBA加载Webview2浏览器内核 代替了ie的webbrowser控件 效果类似 资源 VBS加载webview2控件代替ie的webbrowser Edge
  • Oracle UTL_HTTP(收集汇总有用资料)

    From Oracle The UTL HTTP package makes Hypertext Transfer Protocol HTTP callouts from SQL and PL SQL You can use it to a
  • shell脚本中任意输入三个数,输出最大值

    Linux下用shell脚本任意输入三个数 输出最大值 bin bash read p 请输入第一个数 n1 read p 请输入第二个数 n2 read p 请输入第三个数 n3 max n1 if n2 gt max then max
  • 同态加密简介

    同态加密概述 基本概念 同态加密 Homomorphic Encryption HE 指将原始数据经过同态加密后 对密文进行特定的运算 得到的密文计算结果在进行同态解密后的得到的明文等价于原始明文数据直接进行相同计算所得到的数据结果 历史与
  • 快速加入Health Kit,一文了解审核流程

    HUAWEI Health Kit是为华为生态应用打造的基于华为帐号和用户授权的运动健康数据开放平台 在获取用户授权后 开发者可以使用Health Kit提供的开放能力获取运动健康数据 基于多种类型数据构建运动健康领域应用与服务 为用户打造
  • axios实现本地缓存

    import axios from axios 线上数据库 axios defaults baseURL XXXXXXXXXXXXX 测试数据库 axios defaults baseURL http 192 168 1 25 8080 a
  • QMap和std::map的遍历

    两种遍历方式都使用迭代器 1QMap使用Iterator key 和Iterator value 方法获取第一个或第二个元素的值 而std map使用Iterator gt first Iterator gt second 来获取第一个或第
  • 为什么把系统带宽定义为-3dB?

    原文来自公众号 工程师看海 为什么把系统带宽定义为 3dB 对于我们常说的电路带宽或系统带宽 指的是增益为 3dB时的频率点 为什么选 3dB呢 对于带宽我们可以粗暴的理解为 系统的有效频率范围小于 3dB时的频点 简单来说 比如一个系统
  • 微信小程序练手实战:前端+后端(Java)

    1 前言 现在微信小程序越来越火了 相信不少人都通过各种途径学习过微信小程序或者尝试开发 作者就是曾经由于兴趣了解开发过微信小程序 最终自己的毕业设计也是开发一个微信小程序 所以现在用这篇博客记录我之前开发的一些经验和一些心得吧 2 主要内
  • 【Unity】一键切换是否允许#if UNITY_EDITOR条件编译生效

    在项目中经常会条件编译的方式来让编译器环境和非编译器环境跑不同的代码 但这种方式会让非编译器环境的代码测试变得十分不方便 UNITY EDITOR也是Unity预定义的宏 不能直接在PlayerSettings里面增加或删除 if UNIT
  • github实现在线运行程序

    复制定时任务代码进来 name weixin on workflow dispatch schedule 代表国际标准时间4点0分 北京时间需要 8小时 代表北京时间中午12点运行 cron 30 23 jobs 将工作流程中运行的所有作业
  • Vue h5 调用微信扫码接口

    需求 调用微信扫码接口 然后获取扫码返回结果的url中的参数 携参跳转到其他页面 1 安装微信js sdk 通过yarn安装 yarn add weixin js sdk 通过npm安装 npm i weixin js sdk 2 引用 i
  • 150.逆波兰表达式求值

    目录 一 题目 二 分析 代码 三 中缀表达式转后缀表达式 一 题目 150 逆波兰表达式求值 力扣 LeetCode 二 分析 代码 class Solution public int evalRPN vector
  • python机器学习手写算法系列——线性回归

    本系列另一篇文章 决策树 https blog csdn net juwikuang article details 89333344 本文源代码 https github com juwikuang machine learning st
  • html5和Css3 的参考手册(中文chm版)

    html5的其实就是利用w3c的在线版做成的chm 只是希望对没网络的朋友一点帮助 哈哈 我就是那样有时不能上网的 包含了HTML 5 中的一些新特性 嵌入音频 视频 图片的函数 客户端数据存储 以及交互式文档 其他特性包括新的页面元素 比
  • Maven的安装以及环境变量的配置

    一 Maven的下载 官网下载地址 官网下载地址 历史版本下载地址 历史版本下载地址 点击archives 找到3 6 3版本 找到存放二进制文件的文件夹 下载 二 环境变量配置 1 设置MAVEN HOME 变量名 MAVEN HOME
  • javassist动态生成class

    什么是javassist Javassist是一个开源的分析 编辑和创建Java字节码的类库 是由东京工业大学的数学和计算机科学系的 Shigeru Chiba 千叶 滋 所创建的 它已加入了开放源代码JBoss应用服务器项目 通过使用Ja