Java 代码编译和解析方法信息

使用 javassist 可以操作字节码文件,我分享一下一个简单的编译和类方法解析代码。 

什么是 Javassist?

Javassist 是一个强大的字节码操作工具,它提供了在运行时编辑 Java 字节码的能力。通过Javassist,开发人员可以动态地创建和修改 Java 类
。这使得在不重新编译整个程序的情况下,能够对类进行动态修改和增强。

代码(请勿转载)

package com.hao.insertmu;import javassist.ClassPool;
import javassist.CtClass;
import javassist.bytecode.MethodInfo;
import org.jetbrains.annotations.NotNull;import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;// 8.8 最新版
public class CompileCodeAndAnalyze {public static void main(String[] args) {String javaFilePath = "!!!Java 文件路径!!!!";String classOutputDir = "out";List<ClassAnalysisResult> results = getClassAnalysisResult(javaFilePath, classOutputDir, "major");for (ClassAnalysisResult result : results) {System.out.println(result.getClassName() + "@" + result.getMethodName() + "(" + getParametersDescription(result) + ")");System.out.println("\t Arrays.asList(" + getParametersSimpleName(result) + ")");}boolean isCompiled = compileJavaFile(javaFilePath, classOutputDir);if (isCompiled) {String className = getFullClassName(javaFilePath);List<ClassAnalysisResult> results2 = analyzeClass(className, javaFilePath, classOutputDir, "major");// 打印结果for (ClassAnalysisResult result : results2) {System.out.println(result.getClassName() + "@" + result.getMethodName() + "(" + getParametersDescription(result) + ")");System.out.println("\tReturns: " + result.getReturnType()); // 打印返回类型System.out.println("\tArrays.asList(" + getParametersSimpleName(result) + ")");}} else {System.out.println("Compilation failed.");}}private static String getFullClassName(String javaFilePath) {String packageName = "";String className = "";try (BufferedReader reader = new BufferedReader(new FileReader(javaFilePath))) {String line;while ((line = reader.readLine()) != null) {if (line.startsWith("package")) {packageName = line.substring(line.indexOf("package") + 8, line.indexOf(';')).trim();} else if (line.startsWith("public class") || line.startsWith("class") ||line.startsWith("public static class") || line.startsWith("static class")) {line = line.replace("{", "").trim();className = line.substring(line.lastIndexOf(' ') + 1).trim();break;}}} catch (IOException e) {e.printStackTrace();}return packageName.isEmpty() ? className : packageName + "." + className;}private static boolean checkJavaCompilerVersion(@NotNull JavaCompiler compiler) {String version = System.getProperty("java.version");System.out.println("Java version: " + version);if (version.startsWith("1.")) {version = version.substring(2, 3);} else {int dotIndex = version.indexOf('.');if (dotIndex != -1) {version = version.substring(0, dotIndex);}}int majorVersion = Integer.parseInt(version);if (majorVersion < 8) {System.out.println("Error: JDK version is below 8. Please update to JDK 8 or higher.");return false;} else {System.out.println("Java Compiler version is sufficient (JDK 8 or higher).");return true;}}@SuppressWarnings("ResultOfMethodCallIgnored")public static boolean compileJavaFile(String javaFilePath, String outputDir) {JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();if (compiler == null) {System.out.println("Java Compiler not found. Make sure you're using a JDK.");return false;}if (!checkJavaCompilerVersion(compiler)) {return false;}Path tempDir;try {tempDir = Files.createTempDirectory("compile_output");} catch (IOException e) {System.out.println("Failed to create temporary directory.");return false;}int compilationResult = compiler.run(null, null, null, "-encoding", "utf8", "-parameters", "-d", tempDir.toString(), javaFilePath);if (compilationResult == 0) {System.out.println("Compilation successful.");try {Files.createDirectories(Paths.get(outputDir));Files.walk(tempDir).forEach(source -> {try {Path destination = Paths.get(outputDir, source.toString().substring(tempDir.toString().length()));if (Files.isDirectory(source)) {Files.createDirectories(destination);} else {Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);}} catch (IOException e) {e.printStackTrace();}});} catch (IOException e) {e.printStackTrace();return false;} finally {try {Files.walk(tempDir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);} catch (IOException e) {e.printStackTrace();}}return true;} else {System.out.println("Compilation failed.");return false;}}public static List<ClassAnalysisResult> getClassAnalysisResult(String javaFilePath, String classOutputDir, String logInfoType) {boolean isCompiled = compileJavaFile(javaFilePath, classOutputDir);List<ClassAnalysisResult> results = null;if (isCompiled) {String className = getFullClassName(javaFilePath);results = analyzeClass(className, classOutputDir, classOutputDir, logInfoType);} else {System.out.println("Compilation failed.");}return results;}public static List<ClassAnalysisResult> analyzeClass(String className, String classPath,String classOutputDir, String logInfoType) {List<ClassAnalysisResult> results = new ArrayList<>();try {File file = new File(classOutputDir);ClassLoader classLoader = new URLClassLoader(new java.net.URL[]{file.toURI().toURL()});Class<?> clazz = Class.forName(className, true, classLoader);//System.out.println(className);// 使用你想要解析的类ClassPool pool = ClassPool.getDefault();pool.insertClassPath(classPath);CtClass ctClass = pool.get(className); // 你可以替换为需要解析的类名analyzeClassRecursively(clazz, ctClass, results, logInfoType);} catch (Exception e) {e.printStackTrace();}return results;}private static void analyzeClassRecursively(Class<?> clazz, CtClass ctClass, List<ClassAnalysisResult> results, String logInfoType) {Constructor<?>[] constructors = clazz.getDeclaredConstructors();for (Constructor<?> constructor: constructors) {List<ParameterInfo> parameters = new ArrayList<>();for (Parameter parameter : constructor.getParameters()) {parameters.add(new ParameterInfo(parameter.getName(), parameter.getType().getCanonicalName()));}results.add(new ClassAnalysisResult(clazz.getName(), "<init>", parameters, "void"));}// 解析静态初始化块ClassAnalysisResult result = parseStaticInitializer(ctClass);if(result != null) {results.add(result);}Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {List<ParameterInfo> parameters = new ArrayList<>();for (Parameter parameter : method.getParameters()) {String typeName;// "mujava" 情况的处理if ("mujava".compareTo(logInfoType) == 0) {Class<?> parameterType = parameter.getType();typeName = parameterType.getSimpleName();  // 获取简单名称if (parameterType.isArray()) {// 如果是数组类型,获取其元素类型的简单名称typeName = parameterType.getComponentType().getSimpleName();}} else {// 默认处理方式,获取参数类型的全限定名typeName = parameter.getType().getCanonicalName();}// 添加参数信息parameters.add(new ParameterInfo(parameter.getName(), typeName));}// 获取返回类型String returnType = method.getReturnType().getCanonicalName();results.add(new ClassAnalysisResult(clazz.getName(), method.getName(), parameters, returnType));}Class<?>[] innerClasses = clazz.getDeclaredClasses();for (Class<?> innerClass : innerClasses) {analyzeClassRecursively(innerClass, ctClass, results, logInfoType);}}private static ClassAnalysisResult parseStaticInitializer(CtClass ctClass) {MethodInfo clinitMethodInfo = ctClass.getClassFile().getMethod("<clinit>");if (clinitMethodInfo != null) {return new ClassAnalysisResult(ctClass.getName(), "", new ArrayList<>(), "");}return null;}public static String getParametersDescription(ClassAnalysisResult analysisResult) {if (analysisResult == null) {return "";}List<ParameterInfo> parameters = analysisResult.getParameters();StringBuilder paramsDescription = new StringBuilder();for (int i = 0; i < parameters.size(); i++) {paramsDescription.append(parameters.get(i).getType()).append(" ").append(parameters.get(i).getName());if (i < parameters.size() - 1) {paramsDescription.append(",");}}return paramsDescription.toString();}public static String getParametersTypesName(ClassAnalysisResult analysisResult) {if (analysisResult == null) {return "";}List<ParameterInfo> parameters = analysisResult.getParameters();StringBuilder paramsTypesName = new StringBuilder();for (int i = 0; i < parameters.size(); i++) {paramsTypesName.append(parameters.get(i).getType());if (i < parameters.size() - 1) {paramsTypesName.append(",");}}return paramsTypesName.toString();}public static String getParametersSimpleName(ClassAnalysisResult analysisResult) {if (analysisResult == null) {return "";}List<ParameterInfo> parameters = analysisResult.getParameters();StringBuilder paramsSimpleName = new StringBuilder();for (int i = 0; i < parameters.size(); i++) {paramsSimpleName.append(parameters.get(i).getName());if (i < parameters.size() - 1) {paramsSimpleName.append(",");}}return paramsSimpleName.toString();}public static Map<String, String> getClassInfoHashMap(List<ClassAnalysisResult> analysisResults, String logInfoType) {Map<String, String> infoMap = new HashMap<>();if("major".compareTo(logInfoType) == 0)for (ClassAnalysisResult result:analysisResults) {String flatName;if(result.getMethodName().isEmpty()) {flatName = result.getClassName();} else {flatName = result.getClassName()+ "@" + result.getMethodName()+ "(" + getParametersTypesName(result) + ")";}String paramsList = getParametersSimpleName(result);infoMap.put(flatName, paramsList);}elsefor (ClassAnalysisResult result:analysisResults) {String flatName;flatName = result.getReturnType()+ "_" + result.getMethodName()+ "(" + getParametersTypesName(result) + ")";String paramsList = getParametersSimpleName(result);infoMap.put(flatName, paramsList);}return infoMap;}
}class ClassAnalysisResult {private final String className;private final String methodName;private final List<ParameterInfo> parameters;private final String returnType;public ClassAnalysisResult(String className, String methodName, List<ParameterInfo> parameters, String returnType) {this.className = className;this.methodName = methodName;this.parameters = parameters;this.returnType = returnType;}public String getClassName() {return className;}public String getMethodName() {return methodName;}public List<ParameterInfo> getParameters() {return parameters;}public String getReturnType() {return returnType;}
}class ParameterInfo {private final String name;private final String type;public ParameterInfo(String name, String type) {this.name = name;this.type = type;}public String getName() {return name;}public String getType() {return type;}
}

配合 mujava 或者 major 使用。

调用示例:

// 获取代码的方法签名信息
List<ClassAnalysisResult> results = getClassAnalysisResult(sourceCodeFilePath,"out", logType);

其中,sourceCodeFilePath 为源代码路径,"out" 是输出路径,logType 是格式化输出匹配的工具日志类型(目前支持: mujava、major)。返回类中每个方法的分析结果。

执行效果展示:

 


文章出处链接:[https://blog.csdn.net/qq_59075481/article/details/144888424].

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/500937.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud源码分析-Lettue Redis

redis connection异步发送 底层是nio channel

ELK入门教程(超详细)

什么是ELK&#xff1f; ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称(后来出现的filebeat属于beats家族中的一员&#xff0c;可以用来替代logstash的数据收集功能&#xff0c;比较轻量级)&#xff0c;也被称为Elastic Stack。 Filebeat Filebeat是用于转…

Wireshark和科来网络分析系统

Wireshark 是一款功能强大的网络协议分析工具&#xff0c;主要用于捕获和分析网络流量&#xff0c;帮助用户排查网络问题、进行安全分析和学习网络协议。以下是 Wireshark 的基础使用指南&#xff1a; 1. 安装 Wireshark 访问 Wireshark 官网 下载并安装适合你操作系统的版本…

机器学习之逻辑回归算法、数据标准化处理及数据预测和数据的分类结果报告

逻辑回归算法、数据标准化处理及数据预测和数据的分类结果报告 目录 逻辑回归算法、数据标准化处理及数据预测和数据的分类结果报告1 逻辑回归算法1.1 概念理解1.2 算法导入1.3 算法优缺点 2 LogisticRegression理解2.1查看参数定义2.2 参数理解2.3 方法2.4基本格式 3 数据标准…

家政上门小程序如何创建?家政服务怎么能少了小程序帮手

在如今这个“忙到没时间打扫”的时代&#xff0c;家政服务变得越来越受欢迎。为了提高效率、减少沟通成本&#xff0c;很多家政公司都已经开始借助小程序的力量。那么&#xff0c;家政上门小程序到底该如何创建呢?小程序又是如何帮助家政服务更好地满足客户需求的呢?本文将为…

机器学习-感知机-神经网络-激活函数-正反向传播-梯度消失-dropout

文章目录 感知机工作流程 神经网络区别各种各样的神经网络 激活函数激活函数类型Sigmoid 函数ReLU函数Leaky ReLU 函数Tanh 函数 正向传播反向传播梯度消失(gradient vanish)如何解决 Dropout使用 PyTorch实战神经网络算法(手写MNIST数字识别)viewsoftmax和log-softmaxcross-en…

生态碳汇涡度相关监测与通量数据分析实践技术应用

1.以涡度通量塔的高频观测数据为例&#xff0c;基于MATLAB开展上机操作&#xff1a; 2.涡度通量观测基本概况&#xff1a;观测技术方法、数据获取与预处理等 3.涡度通量数据质量控制&#xff1a;通量数据异常值识别与剔除等 4.涡度通量数据缺失插补&#xff1a;结合气象数据…

Win11电脑Cursor默认打开markdown文件,如何修改markdown文件默认打开方式为Typora?

问题 Windows 11电脑上最近新装了cursor&#xff0c;导致我的markdown文件的默认打开方式被自动设置为cursor&#xff0c;那么我想将默认打开方式设置为Typora&#xff0c;应该怎么做呢&#xff1f; 解决方法 选中一个markdown文件&#xff0c;右击&#xff0c;选择属性。 …

基本算法——回归

目录 创建工程 加载数据 分析属性 创建与评估回归模型 线性回归 回归树 评估 完整代码 结论 本节将通过分析能源效率数据集&#xff08;Tsanas和Xifara&#xff0c;2012&#xff09;学习基本的回归算法。我们将基 于建筑的结构特点&#xff08;比如表面、墙体与屋顶面…

PP模块部分BAPI函数

工艺路线 BAPI_ROUTING_CREATE 创建工艺路线 BAPI_ROUTING_EXISTENCE_CHECK 检查工艺路线是否存在 参考操作集 BAPI_REFSETOFOPERATIONS_CREATE 创建参考操作集 BAPI_REFSETOFOPR_EXISTENCE_CHK 检查参考操作集是否存在 计划订单 BAPI_PLANNEDORDER_CREATE 创建计划订单 BAPI…

【SpringBoot】多数据源事务卡死@DSTransactional,当某一个数据库挂掉了,系统卡死问题解决

记录最近发生并解决的一个问题 原因 在一个事务内&#xff0c;操作多个数据库&#xff0c;当其中一个数据库挂掉后&#xff0c;默认无限重连&#xff0c;导致事务无法正常结束&#xff0c;导致系统卡死 解决 将无限重连改成有限次数即可 datasource:db1:driver-class-name…

迅为RK3568开发板编译Android12源码包-设置屏幕配置

在源码编译之前首先要确定自己想要使用的屏幕并修改源码&#xff0c;在编译镜像&#xff0c;烧写镜像。如下图所示&#xff1a; 第一步&#xff1a;确定要使用的屏幕种类&#xff0c;屏幕种类选择如下所示&#xff1a; iTOP-3568 开发板支持以下种类屏幕&#xff1a; 迅为 LV…

重装操作系统后 Oracle 11g 数据库数据还原

场景描述&#xff1a; 由于SSD系统盘损坏&#xff0c;更换硬盘后重装了操作系统&#xff0c;Oracle数据库之前安装在D盘(另一个硬盘)&#xff0c;更换硬盘多添加一个盘符重装系统后盘符从D变成E&#xff0c;也就是之前的D:/app/... 变成了现在的 E:/app/...&#xff0c;重新安装…

企业二要素如何用C#实现

一、什么是企业二要素&#xff1f; 企业二要素&#xff0c;通过输入统一社会信用代码、企业名称或统一社会信用代码、法人名称&#xff0c;验证两者是否匹配一致。 二、企业二要素适用哪些场景&#xff1f; 例如&#xff1a;信用与金融领域 1.信用评级&#xff1a;信用评级…

丢弃法hhhh

一个好的模型需要对输入数据的扰动鲁棒 丢弃法&#xff1a;在层之间加入噪音&#xff0c;等同于加入正则 h2和h5变成0了 dropout一般作用在全连接隐藏层的输出上 Q&A dropout随机置零对求梯度和求反向传播的影响是什么&#xff1f;为0 dropout属于超参数 dropout固定随…

shell学习数学运算符和字符串(三)

这里写目录标题 一、数学运算符1、基本语法2、expr运算3、(())4、let运算5、bc命令6、中括号[] 二、字符串1、单双引号2、字符串拼接3、获取字符串长度4、字符串提取 一、数学运算符 1、基本语法 ( ( ) ) 或者 (())或者 (())或者{}expr ,-,*,/,%加减乘除取余 2、expr运算 ex…

【Java设计模式-1】单例模式,Java世界的“独苗”

今天咱们要一起探秘Java设计模式中的一个超级有趣又超级实用的家伙——单例模式。想象一下&#xff0c;在Java的代码王国里&#xff0c;有这么一类特殊的存在&#xff0c;它们就像独一无二的“独苗”&#xff0c;整个王国里只允许有一个这样的家伙存在&#xff0c;这就是单例模…

无人机飞手培训机构大量新增,考取飞手证参军入伍还有优势吗?

尽管无人机飞手培训机构大量新增&#xff0c;考取飞手证参军入伍仍然具有显著优势。以下是对这一观点的详细阐述&#xff1a; 一、无人机飞手证在军队中的通用优势 1. 法规遵从与安全保障&#xff1a; 根据《民用无人驾驶航空器系统驾驶员管理暂行规定》等相关法规&#xff0…

计算机网络原理(一)

嘿&#xff01; 新年的第一篇博客&#xff0c;大家新年快乐呀&#xff01;希望大家新的一年要多多进步噢&#xff01; 1.TCP/IP的四层/五层参考模型有哪些层&#xff0c;各层的特点是&#xff1f;计算机网络分层的好处是&#xff1f; TCP/IP 四层参考模型 应用层:直接为用户…

大模型Weekly 03|OpenAI o3发布;DeepSeek-V3上线即开源!

大模型Weekly 03&#xff5c;OpenAI o3发布&#xff1b;DeepSeek-V3上线即开源&#xff01;DeepSeek-V3上线即开源&#xff1b;OpenAI 发布高级推理模型 o3https://mp.weixin.qq.com/s/9qU_zzIv9ibFdJZ5cTocOw?token47960959&langzh_CN 「青稞大模型Weekly」&#xff0c;持…