获取程序启动类

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

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

    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.rhkb.cn/news/496931.html

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

相关文章

Linux应用软件编程-多任务处理(进程)

多任务&#xff1a;让系统具备同时处理多个事件的能力。让系统具备并发性能。方法&#xff1a;进程和线程。这里先讲进程。 进程&#xff08;process&#xff09;&#xff1a;正在执行的程序&#xff0c;执行过程中需要消耗内存和CPU。 进程的创建&#xff1a;操作系统在进程创…

119.【C语言】数据结构之快速排序(调用库函数)

目录 1.C语言快速排序的库函数 1.使用qsort函数前先包含头文件 2.qsort的四个参数 3.qsort函数使用 对int类型的数据排序 运行结果 对char类型的数据排序 运行结果 对浮点型数据排序 运行结果 2.题外话:函数名的本质 1.C语言快速排序的库函数 cplusplus网的介绍 ht…

Element-ui table组件:单元格未溢出,悬浮出现popover提示框

问题视图&#xff1a; 问题定位&#xff1a; 源码中&#xff0c;给开启溢出提示的列单元格都添加了class,并且宽度为实际列宽-1。 若单元格内容宽度100%撑开&#xff0c;则会计算为溢出情况。 处理方法&#xff1a; 单元格内容宽度设置100%-1。

Llama 3 预训练(二)

目录 3. 预训练 3.1 预训练数据 3.1.1 网络数据筛选 PII 和安全过滤 文本提取与清理 去重&#xff08;De-duplication&#xff09; 启发式过滤&#xff08;Heuristic Filtering&#xff09; 基于模型的质量过滤 代码和数学推理数据处理 多语言数据处理 3.1.2 确定数…

打破视障壁垒,百度文心快码无障碍版本助力视障IT从业者就业无“碍”

有AI无碍 钟科&#xff1a;被黑暗卡住的开发梦 提起视障群体的就业&#xff0c;绝大部分人可能只能想到盲人按摩。但你知道吗&#xff1f;视障人士也能写代码。 钟科&#xff0c;一个曾经“被黑暗困住”的人&#xff0c;他的世界&#xff0c;因为一场突如其来的疾病&#xff0c…

黑马Java面试教程_P9_JVM虚拟机

系列博客目录 文章目录 系列博客目录前言1. JVM组成1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;3 41.2 什么是程序计数器&#xff1f;3 4总结 1.3 你能给我详细的介绍Java堆吗? 3 4总结 1.4 什么是虚拟机栈 3 4总结 1.6 能不能解释一下方法区&#xff1f; 3…

修改 ssh 默认访问端口

Linux 最小化安装后默认带有 ssh 服务并正常运行&#xff0c;服务默认端口为“22”。为了确保访问网络的安全&#xff0c;很多用户的网络设备对“22”端口做了限制&#xff0c;这时我们需要修改 ssh 服务默认的端口。 此步骤建议直接在服务器上通过鼠标键盘操作 修改配置文件 …

新手SEO指南如何快速入门与提升网站排名

内容概要 搜索引擎优化&#xff08;SEO&#xff09;是提高网站可见度和排名的重要手段&#xff0c;尤其对新手来说&#xff0c;掌握其基本概念和实用技巧至关重要。本文将针对新手提供一系列的指导&#xff0c;帮助你快速入门并逐步提升网站排名。 首先&#xff0c;了解SEO的…

Springboot高并发乐观锁

Spring Boot分布式锁的主要缺点包括但不限于以下几点&#xff1a; 性能开销&#xff1a;使用分布式锁通常涉及到网络通信&#xff0c;这会引入额外的延迟和性能开销。例如&#xff0c;当使用Redis或Zookeeper实现分布式锁时&#xff0c;每次获取或释放锁都需要与这些服务进行交…

18.springcloud_openfeign之扩展组件二

文章目录 一、前言二、子容器默认组件FeignClientsConfigurationDecoder的注入Contract约定 对注解的支持对类上注解的支持对方法上注解的支持对参数上注解的支持MatrixVariablePathVariableRequestParamRequestHeaderSpringQueryMapRequestPartCookieValue FormattingConversi…

圆排列C++

Description 给定n个大小不等的圆c1,c2,…,cn&#xff0c;现要将这n个圆排进一个矩形框中&#xff0c;且要求各圆与矩形框的底边相切。圆排列问题要求从n个圆的所有排列中找出有最小长度的圆排列。例如&#xff0c;当n3&#xff0c;且所给的3个圆的半径分别为1&#xff0c;1&a…

【玩转OCR】 | 腾讯云智能结构化OCR在多场景的实际应用与体验

文章目录 引言产品简介产品功能产品优势 API调用与场景实践图像增强API调用实例发票API调用实例其他场景 结语相关链接 引言 在数字化信息处理的时代&#xff0c;如何高效、精准地提取和结构化各类文档数据成为了企业和政府部门的重要需求。尤其是在面对海量票据、证件、表单和…

AEO海关认证的注意事项

AEO海关认证的注意事项繁多且至关重要&#xff0c;企业需细致准备&#xff0c;确保万无一失。 首先&#xff0c;企业需深入研读相关政策文件&#xff0c;如《中华人民共和国海关注册登记和备案企业信用管理办法》及《海关高级认证企业标准》&#xff0c;以政策为指引&#xff0…

使用Excel制作通达信自定义外部数据,安排!!!

Excel相信大家电脑上都有这个工具&#xff0c;相比敲编程代码&#xff0c;用这个去做自定义数据对大多数人&#xff0c;应该是比较友好的。自定义数据分为外部序列数据&#xff0c;看了一下内容理解起来比较多&#xff0c;分两期给大家介绍。为了照顾电脑基础薄弱的朋友&#x…

使用c#制作坐标

1、建立坐标 2、坐标系的放大缩小 3、标定刻度 4、实时显示鼠标在坐标系上的坐标 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using S…

计算属性 简写和 完整写法

计算属性渲染不加上括号 methods方法和computed属性区别&#xff1a; computed只计算一次&#xff0c;然后缓存&#xff0c;后续直接拿出来使用&#xff0c;而methods每次使用每次计算&#xff0c;不会缓存 计算属性完整写法&#xff1a; 既获取又设置 slice 截取 成绩案例 …

c++基于过程

前言&#xff1a; 笔记基于C黑马程序员网课视频&#xff1a;黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili 在此发布笔记&#xff0c;只是为方便学习&#xff0c;不做其他用途&#xff0c;原作者为黑马程序员。 1. C基础 1.1 用Visual Studio写C程…

Windows配置cuda,并安装配置Pytorch-GPU版本

文章目录 1. CUDA Toolkit安装2. 安装cuDNN3. 添加环境变量配置Pytorch GPU版本 博主的电脑是Windows11&#xff0c;在安装cuda之前&#xff0c;请先查看pytorch支持的版本&#xff0c;cuda可以向下兼容&#xff0c;但是pytorch不行&#xff0c;请先进入&#xff1a;https://py…

【202】仓库管理系统

-- 基于springboot仓库管理系统设计与实现 开发技术栈: 开发语言 : Java 开发软件 : Eclipse/MyEclipse/IDEA JDK版本 : JDK8 后端技术 : SpringBoot 前端技术 : Vue、Element、HTML、JS、CsS、JQuery 服务器 : Tomcat8/9 管理包 : Maven 数据库 : MySQL5.x/8 数据库工具 : …

Debian安装配置RocketMQ

安装配置 本次安装在/tools/rocket目录下 下载 wget https://dist.apache.org/repos/dist/release/rocketmq/5.3.1/rocketmq-all-5.3.1-bin-release.zip 解压缩 unzip rocketmq-all-5.3.1-bin-release.zip 如果出现以下报错 -bash: unzip: command not found可安装unzip工具后执…