购买域名后怎么建网站/互联网推广的方式
jar包加密方案xjar, 不支持springboot3。这个发个魔改文章希望大家支持
最近公司需要将项目部署在第三方服务器,于是就有了jar包加密的需求,了解了下目前加密方案现况如下:
- 混淆方案,就是在代码中添加大量伪代码,以便隐藏业务代码
- 加密方案,将jar包中的所有class加密,在运行时通过自定义classloader进行解密
目前有的所有加密方案基本思路都跟上面大差不差,在了解了一圈决定使用了xjar这个开源项目。它的实现思路就是方案2.
打开github首页,xjar项目文档还是不错的,clone下来,跟着文档上手,很容易就测试并通过了我的测试项目,接着便推给其他同事使用了。
好景不长,下午就有同事找我,说他的项目加密后不能成功运行。我去看了下,加密操作上没什么问题,但是就是加密包不能成功运行。
报错如下:
错误: 找不到或无法加载主类 null
原因: java.lang.ClassNotFoundException: null
panic: exit status 1
了解了下,同事那边使用了springboot3,而我测试项目是springboot2。 难道不支持springboot3? 我心里想到。
先简单看了下加密的jar包目录结构,很容易就发现以下问题:
- jar包中MANIFEST.MF文件中, Main-Class属性没有值
- jar包中没有将加解密相关的的class打进去
看样子需要进行二开了,唉。 clone项目到本地,拉个新分支。
首先看下源码,在XBootEncryptor
中定义了springboot的classloaderfinal String jarLauncher = "org.springframework.boot.loader.JarLauncher";
这里的jarlauncher在spring3中已经变包路径了。
没想到这么简单,心里暗喜。于是把这里修改为:org.springframework.boot.loader.launch.JarLauncher
。 用spring3搭个demo, 重新打包。
再看jar文件, main-class已经写出去了,xjar相关的包也成功写到jar包。松了口气,看样子没太大问题。
开命令窗口,启动项目,一气呵成。看到终端输出springboot的logo时,心里已经松了口气。
可惜天不遂愿,又打印了几行日志后,抛出以下错误:
2024-09-27T17:51:36.403+08:00 ERROR 3796 --- [demo] [ main] o.s.boot.SpringApplication : Application run failedorg.springframework.beans.factory.BeanDefinitionStoreException: Incompatible class format in URL [jar:nested:/D:/workspace/xiudianer/workspace/transport-mqtt-device-v4/branches/4.0.0/transport-mqtt-device-xjar/src/main/java/com/xd/device/ad/jars/encrypted5.jar/!BOOT-INF/classes/!/com/example/demo/DemoApplication.class]: set system property 'spring.classformat.ignore' to 'true' if you mean to ignore such files during classpath scanningat org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:504) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:351) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:277) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:306) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:246) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:165) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:417) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:607) ~[spring-context-6.1.13.jar!/:6.1.13]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.4.jar!/:3.3.4]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.4.jar!/:3.3.4]at com.example.demo.DemoApplication.main(DemoApplication.java:11) ~[!/:0.0.1-SNAPSHOT]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[encrypted5.jar:0.0.1-SNAPSHOT]at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[encrypted5.jar:0.0.1-SNAPSHOT]at io.xjar.boot.XJarLauncher.launch(XJarLauncher.java:27) ~[encrypted5.jar:0.0.1-SNAPSHOT]at io.xjar.boot.XJarLauncher.main(XJarLauncher.java:23) ~[encrypted5.jar:0.0.1-SNAPSHOT]
Caused by: org.springframework.core.type.classreading.ClassFormatException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that is not supported yet. Consider compiling with a lower '-target' or upgrade your framework version. Affected class: URL [jar:nested:/D:/workspace/xiudianer/workspace/transport-mqtt-device-v4/branches/4.0.0/transport-mqtt-device-xjar/src/main/java/com/xd/device/ad/jars/encrypted5.jar/!BOOT-INF/classes/!/com/example/demo/DemoApplication.class]at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:59) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:48) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:122) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:470) ~[spring-context-6.1.13.jar!/:6.1.13]... 28 common frames omitted
Caused by: java.lang.IllegalArgumentException: nullat org.springframework.asm.ClassReader.<init>(ClassReader.java:262) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.asm.ClassReader.<init>(ClassReader.java:180) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.asm.ClassReader.<init>(ClassReader.java:166) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.asm.ClassReader.<init>(ClassReader.java:287) ~[spring-core-6.1.13.jar!/:6.1.13]at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:56) ~[spring-core-6.1.13.jar!/:6.1.13]... 32 common frames omittedpanic: exit status 1
一脸蒙蔽,这tm是什么错啊。
再看源码,xjar是自定义classloader来加载并解密类,核心就在XBootClassLoader.findClass
。 这里源码中修改并打印下class的文件数据,看看究竟加载的什么鬼~
启动项目发现,class文件已解密,但为啥报错呢?只能使用万能断点大法了,在异常堆栈SimpleMetadataReader.getClassReader
处断点,从这里入手。
该方法反编译源码如下:
private static ClassReader getClassReader(Resource resource) throws IOException {InputStream is = resource.getInputStream();ClassReader var2;try {try {var2 = new ClassReader(is);} catch (IllegalArgumentException var5) {throw new ClassFormatException("ASM ClassReader failed to parse class file - probably due to a new Java class file version that is not supported yet. Consider compiling with a lower '-target' or upgrade your framework version. Affected class: " + resource, var5);}} catch (Throwable var6) {if (is != null) {try {is.close();} catch (Throwable var4) {var6.addSuppressed(var4);}}throw var6;}if (is != null) {is.close();}return var2;}
这里有看到inputstrem,于是断点把inputstream打印输出看下内容,发现这里读取的class文件居然是加密的。那么为啥这里没解密呢? 继续往上跟堆栈。
根据参数Resource, 往上跟可以找到springboot扫描注解组件逻辑,也就是扫描项目中所有有注解的class,然后再调用这个方法读取加载class。 继续去看看这个Resource是怎么创建的。
一路跟,在PathMatchingResourcePatternResolver.doFindPathMatchingJarResources
发现了创建Resource
资源的代码result.add(rootDirResource.createRelative(relativePath));
protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirUrl, String subPattern) throws IOException {URLConnection con = rootDirUrl.openConnection();JarFile jarFile;String jarFileUrl;String rootEntryPath;boolean closeJarFile;if (con instanceof JarURLConnection jarCon) {jarFile = jarCon.getJarFile();jarFileUrl = jarCon.getJarFileURL().toExternalForm();JarEntry jarEntry = jarCon.getJarEntry();rootEntryPath = jarEntry != null ? jarEntry.getName() : "";closeJarFile = !jarCon.getUseCaches();} else {String urlFile = rootDirUrl.getFile();try {int separatorIndex = urlFile.indexOf("*/");if (separatorIndex == -1) {separatorIndex = urlFile.indexOf("!/");}if (separatorIndex != -1) {jarFileUrl = urlFile.substring(0, separatorIndex);rootEntryPath = urlFile.substring(separatorIndex + 2);jarFile = this.getJarFile(jarFileUrl);} else {jarFile = new JarFile(urlFile);jarFileUrl = urlFile;rootEntryPath = "";}closeJarFile = true;} catch (ZipException var17) {if (logger.isDebugEnabled()) {logger.debug("Skipping invalid jar class path entry [" + urlFile + "]");}return Collections.emptySet();}}try {if (logger.isTraceEnabled()) {logger.trace("Looking for matching resources in jar file [" + jarFileUrl + "]");}if (StringUtils.hasLength(rootEntryPath) && !rootEntryPath.endsWith("/")) {rootEntryPath = rootEntryPath + "/";}Set<Resource> result = new LinkedHashSet(64);Enumeration<JarEntry> entries = jarFile.entries();while(entries.hasMoreElements()) {JarEntry entry = (JarEntry)entries.nextElement();String entryPath = entry.getName();if (entryPath.startsWith(rootEntryPath)) {String relativePath = entryPath.substring(rootEntryPath.length());if (this.getPathMatcher().match(subPattern, relativePath)) {result.add(rootDirResource.createRelative(relativePath)); // 注意这里,创建了resource资源}}}LinkedHashSet var22 = result;return var22;} finally {if (closeJarFile) {jarFile.close();}}}
上面的代码创建了resource资源,于是继续跟进继续跟进createRelative
方法,那么问题来了,为啥springboot2没问题,spring3读取出来的却又是加密的,这是为毛?
最简单的方法就是对比着看, 两个版本方法如下:
springboot3
protected URL createRelativeURL(String relativePath) throws MalformedURLException {if (relativePath.startsWith("/")) {relativePath = relativePath.substring(1);}return ResourceUtils.toRelativeURL(this.url, relativePath);}
springboot2
@Overridepublic Resource createRelative(String relativePath) throws MalformedURLException {if (relativePath.startsWith("/")) {relativePath = relativePath.substring(1);}return new UrlResource(new URL(this.url, relativePath));}
上边代码一眼看,也没太大问题。都是通过url创建了一个资源链接而已,为毛就是跑步起来呢。 再次祭出断点大法。
断点后发现,两个创建的资源中, URL
属性中的URLStreamHandler
有很大区别。springboot2中该属性为xjar的解密器,二springboot3中却是一个简单的文件读取器。
为啥呢,喔翻了下源码发现在springboot2中,创建Resouces
实例时,url属性实例是直接new出来的,当前类的解密器也就是this.url
中URLStreamHandler
,将会在URL
的构造器中得到继承,所以新Resource读取时也就会解密了
但在springboot3中,ResourceUtils.toRelativeURL
方法中创建URL时是先构建URI实例,再创建URL实例,这个过程中把this.URLStreamHandler
丢失了。
原因找到了,看了下springboot github的issue,官方确实变更了,原因是因为springboot2中的URL
的构造函数在之后的jdk20标记为废弃,所以就改了实现方法。不过官方表示下个版本会兼容处理这个问题,目前spring3最新版为3.3.4
但问题是我们现在就要用啊,只能拉个分支魔改了。
想想思路,既然旧版本没问题,那么喔先把spring-core
包中的这个方法还原为老版本,看看spring能正常跑起来不。测试了下,没问题。
其实这里基本就没问题了,实际项目中只要把这个spring-core包从私仓中替换,项目加密也就没有太大的毛病,但是这样对于追求完美的我来说,方便性还差点。毕竟如果使用了springboot3的多个版本,不可能每个都去修改替换下啊,想想都好麻烦
那就再扩展下吧,既然自定义了classloader,那我可以在类加载过程中通过asm
修改加载中的该方法的字节码,将UrlResource.createRelative
方法逻辑替换为老版本。
由于asm是通过字节码来修改方法的,根据java源码来写出字节码,小弟还没有那个功力。
取个巧,直接使用javap -verbose URLResource.class
来查看老版本这个方法的指令流程
public org.springframework.core.io.Resource createRelative(java.lang.String) throws java.net.MalformedURLException;descriptor: (Ljava/lang/String;)Lorg/springframework/core/io/Resource;flags: (0x0001) ACC_PUBLICCode:stack=6, locals=2, args_size=20: aload_11: ldc #36 // String /3: invokevirtual #37 // Method java/lang/String.startsWith:(Ljava/lang/String;)Z6: ifeq 159: aload_110: iconst_111: invokevirtual #38 // Method java/lang/String.substring:(I)Ljava/lang/String;14: astore_115: new #39 // class org/springframework/core/io/UrlResource18: dup19: new #13 // class java/net/URL22: dup23: aload_024: getfield #6 // Field url:Ljava/net/URL;27: aload_128: invokespecial #40 // Method java/net/URL."<init>":(Ljava/net/URL;Ljava/lang/String;)V31: invokespecial #41 // Method "<init>":(Ljava/net/URL;)V34: areturnLineNumberTable:line 238: 0line 239: 9line 241: 15LocalVariableTable:Start Length Slot Name Signature0 35 0 this Lorg/springframework/core/io/UrlResource;0 35 1 relativePath Ljava/lang/String;StackMapTable: number_of_entries = 1frame_type = 15 /* same */Exceptions:throws java.net.MalformedURLException
然后使用asm转译下,以下为实现核心代码:
@Overridepublic MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);if (name.equals("createRelative") && desc.equals("(Ljava/lang/String;)Lorg/springframework/core/io/Resource;")) {// 修改原方法的字节码mv = new MyMethodVisitor(mv) ;}return mv;}//MyMethodVisitor的结构public class MyMethodVisitor extends MethodVisitor {private final MethodVisitor target;public MyMethodVisitor(MethodVisitor mv) {super(ASM9, null);this.target = mv;}//此方法在目标方法调用之前调用,所以前置操作可以在这处理@Overridepublic void visitCode() {target.visitCode();target.visitCode();target.visitVarInsn(ALOAD, 1);Label A = new Label();Label B = new Label();target.visitLdcInsn("/");target.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "startsWith", "(Ljava/lang/String;)Z", false);target.visitJumpInsn(IFEQ, A);target.visitVarInsn(ALOAD, 1);target.visitInsn(ICONST_1);target.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "substring", "(I)Ljava/lang/String;", false);target.visitVarInsn(ASTORE, 1);target.visitJumpInsn(GOTO,B);target.visitLabel(A);target.visitLabel(B);target.visitTypeInsn(Opcodes.NEW, "org/springframework/core/io/UrlResource");target.visitInsn(DUP);target.visitTypeInsn(Opcodes.NEW, "java/net/URL");target.visitInsn(DUP);target.visitVarInsn(ALOAD, 0);target.visitFieldInsn(GETFIELD, "org/springframework/core/io/UrlResource", "url", "Ljava/net/URL;");target.visitVarInsn(ALOAD, 1);target.visitMethodInsn(INVOKESPECIAL, "java/net/URL", "<init>", "(Ljava/net/URL;Ljava/lang/String;)V", false);target.visitMethodInsn(INVOKESPECIAL, "org/springframework/core/io/UrlResource", "<init>", "(Ljava/net/URL;)V", false);target.visitInsn(ARETURN); //target.visitMaxs(6, 2);target.visitEnd();}@Overridepublic void visitMaxs(int maxStack, int maxLocals) {super.visitMaxs(maxStack + 1, maxLocals);}}
最后,由于classloader中使用了asm
,所以也需要将asm提前打到加密jar包 中。
然后再来编译一个加密包,再启动,成功!
这样道友们就可以直接使用项目,不必去修改spring-core
包了。
项目传送地址:https://github.com/MisterChangRay/xjar4springboot3
这个只支持springboot3哟~ 好用点个赞。把
相关文章:

魔改xjar支持springboot3,
jar包加密方案xjar, 不支持springboot3。这个发个魔改文章希望大家支持 最近公司需要将项目部署在第三方服务器,于是就有了jar包加密的需求,了解了下目前加密方案现况如下: 混淆方案,就是在代码中添加大量伪代码,以便隐藏业务代…...

python json文件读写
在Python中处理JSON文件是一个常见的任务。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python提供了内置的json模块来帮助我们读取和写入JSON格式的数据。 如何读…...

Android常用C++特性之std::find_if
声明:本文内容生成自ChatGPT,目的是为方便大家了解学习作为引用到作者的其他文章中。 std::find_if 是 C 标准库中的一个算法,用于在给定范围内查找第一个满足特定条件的元素。它接受一个范围(由迭代器指定)和一个谓词…...

19 vue3之自定义指令Directive按钮鉴权
directive-自定义指令(属于破坏性更新) Vue中有v-if,v-for,v-bind,v-show,v-model 等等一系列方便快捷的指令 今天一起来了解一下vue里提供的自定义指令 Vue3指令的钩子函数 created 元素初始化的时候beforeMount 指令绑定到元素后调用 只调用一次mounted 元素插入父级dom…...

数据资产新范式,URP城市焕新平台东博会首发!
城市数据资产蕴藏着巨大的宝藏。今年1月,国家数据局印发《“数据要素”三年行动计划(2024—2026年)》,将“数据要素智慧城市”上升为“数据要素”计划的重要部分,加速释放城市数据资产价值。 高质量发展以数据要素驱动…...

儿童乐园软件下载安装 佳易王游乐场会员扣次管理系统操作教程
一、前言 儿童乐园软件下载安装 佳易王游乐场会员扣次管理系统操作教程 软件为绿色免安装版,已经内置数据库,不需再安装数据库文件,软件解压即可。 二、软件程序教程 1、软件可同时管理多个项目,项目设置方法如图,点…...

windows下 Winobj.exe工具使用说明c++
1、winobj.exe工具下载地址 WinObj - Sysinternals | Microsoft Learn 2、接下来用winobj.exe查看全局互斥,先写一个小例子 #include <iostream> #include <stdlib.h> #include <tchar.h> #include <string> #include <windows.h>…...

提示词工程 (Prompt Engineering) 最佳实践
prompt Engineering 概念解析 提示工程是一门较新的学科,关注提示词开发和优化,帮助用户将大语言模型(Large Language Model, LLM)用于各场景和研究领域。研究人员可利用提示工程来提升大语言模型处理复杂任务场景的能力…...

【读写分离?聊聊Mysql多数据源实现读写分离的几种方案】
文章目录 一.什么是MySQL 读写分离二.读写分离的几种实现方式(手动控制)1.基于Spring下的AbstractRoutingDataSource1.yml2.Controller3.Service实现4.Mapper层5.定义多数据源6.继承Spring的抽象路由数据源抽象类,重写相关逻辑7. 自定义注解WR,用于指定当…...

C++游戏
宠粉福利! 目录 1.猜数字 2.五子棋 3.打怪 4.跑酷 5.打飞机 6.扫雷 1.猜数字 #include <iostream> #include <cstdlib> #include <ctime>int main() {std::srand(static_cast<unsigned int>(std::time(0))); // 设置随机数种子int …...

探索顶级低代码开发平台,实现创新
文章盘点ZohoCreator、OutSystems等10款顶尖低代码开发平台,各平台以快速开发、集成、数据安全等为主要特点,适用于不同企业需求,助力数字化转型。 一、Zoho Creator Zoho Creator 是一个低代码开发平台,它简化了应用开发中的复杂…...

Html--笔记01:使用软件vscode,简介Html5--基础骨架以及标题、段落、图片标签的使用
一.使用VSC--全称:Visual Studio Code vscode用来写html文件,打开文件夹与创建文件夹:①选择文件夹 ②拖拽文件 生成浏览器的html文件的快捷方式: !enter 运行代码到网页的方法: 普通方法:…...

探索反向传播:深度学习中优化神经网络的秘密武器
反向传播的概念: 反向传播(Backpropagation) 是深度学习中训练神经网络的核心算法。它通过有效计算损失函数相对于模型参数的梯度,使得模型能够通过梯度下降等优化方法逐步调整参数,从而最小化损失函数,提…...

K8S精进之路-控制器DaemonSet -(3)
介绍 DaemonSet就是让一个节点上只能运行一个Daemonset Pod应用,每个节点就只有一个。比如最常用的网络组件,存储插件,日志插件,监控插件就是这种类型的pod.如果集群中有新的节点加入,DaemonSet也会在新的节点创建出来…...

【JVM】类加载机制
文章目录 类加载机制类加载过程1. 加载2. 验证3. 准备4. 解析偏移量符号引用和直接引用 5. 初始化 类加载机制 类加载指的是,Java 进程运行的时候,需要把 .class 文件从硬盘读取到内存,并进行一些列的校验解析的过程(程序要想执行…...

ENV | 5步安装 npm node(homebrew 简洁版)
1. 操作步骤 1.1 安装 homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"1.2 安装 node # 安装最新版 brew install node # 安装指定版本,如18 brew install node181.3 安装 nvm(…...

EasyExcel全面实战:掌握多样化的Excel导出能力
1 概述 本文将通过实战案例全面介绍EasyExcel在Excel导出方面的多种功能。内容涵盖多表头写入、自定义格式、动态表头生成、单元格合并应用等。通过这些实例,读者可以掌握EasyExcel的各种高级功能,并在实际项目中灵活应用。 白日依山尽,黄河入海流。 欲穷千里目,更上一层楼…...

基于springcloud的药品销售系统
文未可获取一份本项目的java源码和数据库参考。 一、选题背景与意义 1. 选题背景 在日常医药管理中,面对众多的药品和众多不同需求的顾客,每天都会产生大量的数据信息。以传统的手工方式来处理这些信息,操作比较繁琐,且效率低下…...

基于组网分割的超大规模设计 FPGA 原型验证解决方案
引言 如何快速便捷的完成巨型原型验证系统的组网,并监测系统的连通性及稳定性? 如何将用户设计快速布局映射到参与组网的原型验证系统的每一块 FPGA? 随着用户设计规模的日益增大,传统基于单片 FPGA 或单块电路板的原型验证系统…...

C# 面向对象基础,简单的银行存钱取钱程序
题目: 代码实现: BankAccount部分: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Bank {internal class BankAccount{private decimal balance 0;//账…...

【Rockchip系列】官方函数:drm_buf_alloc
drm_buf_alloc 函数 功能 分配一个DRM(Direct Rendering Manager)缓冲区。 语法 void* drm_buf_alloc(int width, int height, int bpp, int* fd, int* handle, size_t* size, int flags);参数 width: 缓冲区宽度(像素)heigh…...

深度学习--------------------------------门控循环单元GRU
目录 门候选隐状态隐状态门控循环单元GRU从零开始实现代码初始化模型参数定义隐藏状态的初始化函数定义门控循环单元模型训练该部分总代码简洁代码实现 做RNN的时候处理不了太长的序列,这是因为把整个序列信息全部放在隐藏状态里面,当时间很长的话&#…...

【实战】| X小程序任意用户登录
复现步骤 在登陆时,弹出这个页面时 抓包,观察数据包的内容 会发现有mobile值(密文)和iv值(随机数),拿到密文,肯定时想到解密,想要解密就必须知道密文,…...

计算机毕业设计之:云中e百货微信小程序设计与实现(源码+文档+定制)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...

CEX上币趋势分析:Infra赛道与Ton生态的未来
在当前的加密市场中,CEX(中心化交易所)上币的选择愈发重要,尤其是对项目方而言。根据 FMG 的整理,结合「杀破狼」的交易所上币信息,显然 Infra 赛道成为了交易所的热门选择,而 Ton 生态也展现出…...

数组基础(c++)
第1题 精挑细选 时限:1s 空间:256m 小王是公司的仓库管理员,一天,他接到了这样一个任务:从仓库中找出一根钢管。这听起来不算什么,但是这根钢管的要求可真是让他犯难了,要求如下&#x…...

第十三届蓝桥杯真题Python c组A.排列字母(持续更新)
博客主页:音符犹如代码系列专栏:蓝桥杯关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 【问题描述】 小蓝要把一个字符串中的字母按其在字母表中的顺序排列。 例如&a…...

IDEA自动清理类中未使用的import包
目录 1.建议清理包的理由 2.清理未使用包的方式 2.1 手动快捷键清理 2.2 设置自动清理 1.建议清理包的理由 有时候项目类文件中会有很多包被引入了,但是并没有被使用,这会增加项目的编译时间并且代码可读性也会变差。在开发过程中,建议设…...

加工零件C++
题目: 样例解释: 样例#1: 编号为 1 的工人想生产第 1 阶段的零件,需要编号为 2 的工人提供原材料。 编号为 2 的工人想生产第 1 阶段的零件,需要编号为 1 和 3 的工人提供原材料。 编号为 3 的工人想生产第 1 阶段的零件&#x…...

Etcd 是一个分布式的键值存储系统,用于共享配置和服务发现
Etcd 是一个分布式的键值存储系统,用于共享配置和服务发现。它最初由 CoreOS 开发,并已成为许多分布式系统中的关键组件之一,特别是在 Kubernetes 中扮演着核心角色。Etcd 的设计目标是简单、可靠、安全,并且易于使用。 Etcd 的特…...