spring boot jar 启动报错 Zip64 archives are not supported
spring boot jar 启动报错 Zip64 archives are not supported
- 原因、解决方案
- 问题
- 为什么 spring boot 不支持 zip64
- zip、zip64 功能上的区别
- zip 的文件格式
- spring-boot-loader 是如何判断是否是 zip64 的?
- 参考
spring boot 版本是 2.1.8.RELEASE,引入以下 phoenix 依赖之后启动报错。
<dependency><groupId>org.apache.phoenix</groupId><artifactId>phoenix-client-hbase-2.4</artifactId><version>5.1.3</version>
</dependency>
错误日志:
PS D:\project\java\zip64\target> java -jar .\zip64-0.0.1-SNAPSHOT.jar
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/phoenix-client-hbase-2.4-5.1.3.jarat org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:108)at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:87)at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:69)at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
Caused by: java.io.IOException: Unable to open nested jar file 'BOOT-INF/lib/phoenix-client-hbase-2.4-5.1.3.jar'at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:258)at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:244)at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:104)... 4 more
Caused by: java.lang.IllegalStateException: Zip64 archives are not supportedat org.springframework.boot.loader.jar.CentralDirectoryEndRecord.getNumberOfRecords(CentralDirectoryEndRecord.java:121)at org.springframework.boot.loader.jar.JarFileEntries.visitStart(JarFileEntries.java:117)at org.springframework.boot.loader.jar.CentralDirectoryParser.visitStart(CentralDirectoryParser.java:85)at org.springframework.boot.loader.jar.CentralDirectoryParser.parse(CentralDirectoryParser.java:56)at org.springframework.boot.loader.jar.JarFile.<init>(JarFile.java:125)at org.springframework.boot.loader.jar.JarFile.<init>(JarFile.java:112)at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:289)at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:266)at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:255)
原因、解决方案
Google 很快就找到了原因,stackoverflow 上有类似的问题 java - Add more than 65535 entries jar in Spring boot - Stack Overflow。
第一个回答给出了原因:spring boot 不支持一个 jar 文件中多于 65534(这里应该写错了,应该是 65535) 个文件,并附上了抛异常的代码。
第二个回答是 spring boot 的 issues,有兴趣的可以自己看一下 Support zip64 format executable archives · Issue #2895 · spring-projects/spring-boot (github.com)
第三个回答给出了解决办法:升级到 2.2.x,也给出了支持 zip64 的提交记录 Support zip64 jars by cvienot · Pull Request #16091 · spring-projects/spring-boot (github.com)。我升级成 2.2.0.RELEASE 确实解决了问题。
问题
回答一中的代码来自 spring-boot-loader
子项目中的 org.springframework.boot.loader.jar.CentralDirectoryEndRecord#getNumberOfRecords
方法,依赖如下:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-loader</artifactId><version>2.1.8.RELEASE</version>
</dependency>
为什么 spring boot 不支持 zip64
从 ZIP (file format) - Wikipedia 中可以看出 zip、zip64 在文件的格式上是不同的。猜测应该是开发者没想到 jar 包里的文件个数或 jar 包的大小会超过 65535,所以没有实现 zip64 相关的。从以下提交中能看出一二。直到最后的两个提交才有人实现了 zip64 的相关代码。
zip、zip64 功能上的区别
zip64 格式是标准 zip 格式的扩展,实际上消除了 zip 存档中文件大小和数量的限制。
每种格式允许的最大值总结如下:
Standard Format Zip64 Format Number of Files Inside an Archive 65,535 2^64 - 1 Size of a File Inside an Archive [bytes] 4,294,967,295 2^64 - 1 Size of an Archive [bytes] 4,294,967,295 2^64 - 1 Number of Segments in a Segmented Archive 999 (spanning) 65,535 (splitting) 4,294,967,295 - 1 Central Directory Size [bytes] 4,294,967,295 2^64 - 1
zip 的文件格式
zip格式压缩包主要由三大部分组成:
数据区
、中央目录记录区(也有叫核心目录记录)
、中央目录记录尾部区
。数据区是由一系列
本地文件记录
组成,本地文件记录主要是记录了压缩前后文件的元数据
以及存放压缩后的文件
。中央目录记录区是有一系列
中央目录记录
所组成,一条中央目录记录
对应数据区中的一个压缩文件记录
。中央目录记录尾部(End of central directory record)主要作用是用来定位
中央目录记录区的开始位置
,同时记录压缩包的注释内容
。
End of central directory record (EOCD)
Offset | Bytes | Description[33] | 中文 |
---|---|---|---|
0 | 4 | End of central directory signature = 0x06054b50 | 签名 |
4 | 2 | Number of this disk (or 0xffff for ZIP64) | |
6 | 2 | Disk where central directory starts (or 0xffff for ZIP64) | |
8 | 2 | Number of central directory records on this disk (or 0xffff for ZIP64) | |
10 | 2 | Total number of central directory records (or 0xffff for ZIP64) | 文件数量(ZIP64 为 0xffff ) |
12 | 4 | Size of central directory (bytes) (or 0xffffffff for ZIP64) | |
16 | 4 | Offset of start of central directory, relative to start of archive (or 0xffffffff for ZIP64) | |
20 | 2 | Comment length (n) | 注释长度 |
22 | n | Comment |
spring-boot-loader 是如何判断是否是 zip64 的?
// 从 bytes 的 offset 偏移量开始,以小端模式读取 length 个字节
public static long littleEndianValue(byte[] bytes, int offset, int length) {long value = 0;for (int i = length - 1; i >= 0; i--) {value = ((value << 8) | (bytes[offset + i] & 0xFF));}return value;
}
/*** A ZIP File "End of central directory record" (EOCD).** @author Phillip Webb* @author Andy Wilkinson* @see <a href="https://en.wikipedia.org/wiki/Zip_%28file_format%29">Zip File Format</a>*/
class CentralDirectoryEndRecord {// EOCD 最小长度,从表中可以看出在没有注释的情况下是 22private static final int MINIMUM_SIZE = 22;// 从表中可以看出注释长度为 2 字节,所有最大值是 65535private static final int MAXIMUM_COMMENT_LENGTH = 0xFFFF;private static final int MAXIMUM_SIZE = MINIMUM_SIZE + MAXIMUM_COMMENT_LENGTH;// EOCD 开始的标记private static final int SIGNATURE = 0x06054b50;// EOCD 中“注释长度”字段的偏移量,从表中可以看出是 20private static final int COMMENT_LENGTH_OFFSET = 20;// 每次从文件尾部读取 256 字节private static final int READ_BLOCK_SIZE = 256;// 最终是 EOCD 的字节数组private byte[] block;// EOCD 在 block 中的偏移量private int offset;// EOCD 的字节数private int size;/*** Create a new {@link CentralDirectoryEndRecord} instance from the specified* {@link RandomAccessData}, searching backwards from the end until a valid block is* located.* @param data the source data* @throws IOException in case of I/O errors*/CentralDirectoryEndRecord(RandomAccessData data) throws IOException {// 从文件尾部读取 256 字节this.block = createBlockFromEndOfData(data, READ_BLOCK_SIZE);this.size = MINIMUM_SIZE;this.offset = this.block.length - this.size;// 尝试找到 EOCD 的开头while (!isValid()) {this.size++;if (this.size > this.block.length) {if (this.size >= MAXIMUM_SIZE || this.size > data.getSize()) {throw new IOException("Unable to find ZIP central directory " + "records after reading " + this.size + " bytes");}// 每次多读 1 字节this.block = createBlockFromEndOfData(data, this.size + READ_BLOCK_SIZE);}// offset 每次向前移动 1 字节this.offset = this.block.length - this.size;}}private byte[] createBlockFromEndOfData(RandomAccessData data, int size) throws IOException {int length = (int) Math.min(data.getSize(), size);return data.read(data.getSize() - length, length);}// 尝试找到 EOCD 的开头private boolean isValid() {// 长度小于 EOCD 的最小长度,肯定不符合if (this.block.length < MINIMUM_SIZE// 读取 block 最开始的 4 个字节,与 EOCD 的标记进行比较,不符合则返回 false// 如果相等则找到了 EOCD 的开头|| Bytes.littleEndianValue(this.block, this.offset + 0, 4) != SIGNATURE) {return false;}// 读取注释长度 2 字节// Total size must be the structure size + commentlong commentLength = Bytes.littleEndianValue(this.block, this.offset + COMMENT_LENGTH_OFFSET, 2);// EOCD 的字节数肯定等于 EOCD 的最小长度 + 注释内容的长度return this.size == MINIMUM_SIZE + commentLength;}/*** Return the number of ZIP entries in the file.* @return the number of records in the zip*/public int getNumberOfRecords() {// 读取 block 偏移量文 10 的 2 个字节,即文件数量long numberOfRecords = Bytes.littleEndianValue(this.block, this.offset + 10, 2);// 如果文件数量为 65535 则为 Zip64if (numberOfRecords == 0xFFFF) {throw new IllegalStateException("Zip64 archives are not supported");}return (int) numberOfRecords;}}
参考
- java - Add more than 65535 entries jar in Spring boot - Stack Overflow
- 压缩包Zip格式详析(全网最详细)_zip格式详解-CSDN博客
- ZIP文件格式分析 | Sp4n9x’s Blog
- ZIP (file format) - Wikipedia
相关文章:
spring boot jar 启动报错 Zip64 archives are not supported
spring boot jar 启动报错 Zip64 archives are not supported 原因、解决方案问题为什么 spring boot 不支持 zip64zip、zip64 功能上的区别zip 的文件格式spring-boot-loader 是如何判断是否是 zip64 的? 参考 spring boot 版本是 2.1.8.RELEASE,引入以…...
BASH and SH in SHELL scripts
一、执行脚本的现象 为了测试一个小的功能,写了一个小脚本,类似的内容如下: #!/bin/shecho "start api test ......"for((i1;i<10;i)); do echo "cur id :" $i; done echo "end."执行一下,“…...
Qt Creator创建一个用户登录界面
目录 1 界面设计 2 代码 2.1 登录界面 2.2 注册界面 2.3 登陆后的界面 3 完整资源 这里主要记录了如何使用Qt Creator创建一个用户登录界面,能够实现用户的注册和登录功能,注册的用户信息存储在了一个文件之中,在登录时可以比对登录信息…...
等保测评练习卷14
等级保护初级测评师试题14 姓名: 成绩: 判断题(10110分) 1. 方案编制活动中测评对象确定、测评指…...
学懂C#编程:常用高级技术——学会C#多线程开发(三):学会线程池的使用
在C#中,线程池(ThreadPool)是一种用于管理线程的机制,它可以有效地重用线程,减少线程创建和销毁的开销,从而提高程序的性能。线程池通常用于执行不需要立即完成的任务,如后台任务、异步操作等。…...
maven-gpg-plugin插件
开源项目SDK:https://github.com/mingyang66/spring-parent 个人文档:https://mingyang66.github.io/raccoon-docs/#/ 一、敏感信息泄漏警告 执行mvn install或mvn deploy时控制台会报如下告警: [WARNING] Parameter passphrase (user pr…...
Linux——echo命令,管道符,vi/vim 文本编辑器
1.echo 命令 作用 向终端设备上输出字符串或变量的存储数据 格式 echo " 字符串 " echo $ 变 量名 [rootserver ~] # echo $SHELL # 输出变量的值必须加 $ /bin/bash [rootserver ~] # str1" 我爱中国 " # 自定义变量 echo 重定向输出到文件 ec…...
CISCN--西南半决赛--pwn
1.vuln 这是主函数,数一下就发现可以溢出最后的0x4008d0 然后会执行到这里,逻辑就是在v0上写shellcode,不过执行写0x10,不够sh,很明显要先read。 以下是exp: from pwn import * context.archamd64 ioprocess(./vuln)…...
DIYGW UniApp低代码可视化平台:高效、灵活、安全的应用开发新途径
一、引言 在数字化快速发展的今天,企业对于快速构建多端应用的需求日益增长。然而,传统的应用开发方式往往面临周期长、成本高、技术门槛高等问题。为了解决这些问题,DIYGW UniApp低代码可视化平台应运而生,它以高效率、多端使用…...
Python爬虫技术及其原理探秘
导言 随着互联网的发展,大量的数据被存储在网络上,而我们需要从中获取有用的信息。Python作为一种功能强大且易于学习的编程语言,被广泛用于网络爬虫的开发。本文将详细介绍Python爬虫所需的技术及其原理,并提供相关的代码案例。…...
堆和栈的区别及应用场景
堆和栈的区别及应用场景 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在计算机科学和编程领域,堆(Heap)和栈(…...
vant的dialog触发了其他overlay
原代码: <!-- dialog --><van-dialog v-model"showTipsDialog" title"温馨提示"><p>dialog内容</p></van-dialog><!-- overlay --><van-overlay style"display: flex" :show"showLoadingOverlay&q…...
Linux驱动开发笔记(十二)并发与竞争
文章目录 前言一、并发与竞争的引入1.1 并发1.2 竞争1.3 解决方法 二、原子操作2.1 概念2.2 使用方法 三、自旋锁3.1 概念3.2 使用方法3.3 自旋锁死锁 四、信号量4.1 概念4.2 使用方法 五、互斥锁5.1 概念5.2 使用方法 前言 Linux的子系统我们已经大致学习完了,笔者…...
【Mac】Listen 1 for Mac(最强的音乐搜索工具)软件介绍
软件介绍 Listen 1 for Mac 是一款非常方便的音乐播放软件,主要功能是集成多个音乐平台,让用户可以方便地搜索、播放和管理音乐。它是一个用 Python 语言开发的免费开源综合音乐搜索工具项目,最大的亮点在于可以搜索和播放来自网易云音乐&am…...
nginx 1024 worker_connections are not enough while connecting to upstream
现象 请求api响应慢,甚至出现504 gateway timeout,重启后端服务不能恢复,但重启nginx可以恢复。 解决方案 worker_connections使用了默认值 1024,当流量增长时,导致连接不够 在nginx.conf中修改连接数就可以了&…...
在Ubuntu 16.04上安装和配置Elasticsearch的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 Elasticsearch 是一个用于实时分布式搜索和数据分析的平台。它因易用性、强大功能和可扩展性而备受欢迎。 Elasticsearch 支持 R…...
C#给SqlSugar封装一个单例类
.NET兼职社区 可以直接用,轻量方便,无需重复造轮子。 这里只对CRUD进行封装,我的应用比较简单。 using SqlSugar; using System.Collections.Generic;namespace MusicApp.Assist {internal class SqlSugarAssist{private static readonly ob…...
Postman接口测试工具的原理及应用详解(六)
本系列文章简介: 在当今软件开发的世界中,接口测试作为保证软件质量的重要一环,其重要性不言而喻。随着前后端分离开发模式的普及,接口测试已成为连接前后端开发的桥梁,确保前后端之间的数据交互准确无误。在这样的背景…...
【算法 之插入排序 原理及案例】
插入排序原理: 插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常…...
第一节:如何开发第一个spring boot3.x项目(自学Spring boot 3.x的第一天)
大家好,我是网创有方,从今天开始,我会记录每篇我自学spring boot3.x的经验。只要我不偷懒,学完应该很快,哈哈,更新速度尽可能快,想和大佬们一块讨论,如果需要讨论的欢迎一起评论区留…...
JS逆向:由 words 、sigBytes 引发的一系列思考与实践
【作者主页】:小鱼神1024 【擅长领域】:JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 在做JS逆向时,你是否经常看到 words 和 sigBytes 这两个属性呢,比如ÿ…...
计算机的错误计算(十五)
摘要 介绍历史上由于计算精度问题引起的灾难或事件。 今天换个话题,说说历史上曾经发生过的一些事件。 1961 年 , 美国麻省理工学院气象学家洛伦兹在仿真天气预报时 , 将 0.506127 舍入到 0.506 , 所得计算结果大相径庭 ! 这种“差之毫厘 , 谬以千里”的现象…...
制作img文件
安装软件包 sudo apt-get install dosfstools dump parted kpartx 创建空白img文件 sudo dd if/dev/zero ofraspberrypi.img bs1M count4000 给img文件分区 sudo parted raspberrypi.img --script -- mklabel msdos sudo parted raspberrypi.img --script -- mkpart primar…...
GB28181视频汇聚平台EasyCVR接入Ehome设备视频播放出现异常是什么原因?
多协议接入视频汇聚平台EasyCVR视频监控系统采用了开放式的架构,系统可兼容多协议接入,包括市场标准协议:国标GB/T 28181协议、GA/T 1400协议、JT808、RTMP、RTSP/Onvif协议;以及主流厂家私有协议及SDK,如:…...
Java利用poi实现word,excel,ppt,pdf等各类型文档密码检测
介绍 最近工作上需要对word,excel,ppt,pdf等各类型文档密码检测,对文件进行分类,有密码的和没密码的做区分。查了一堆资料和GPT都不是很满意,最后东拼西凑搞了个相对全面的检测工具代码类,希望能给需要的人带来帮助。 说明 这段…...
顺序表与链表学习笔记
顺序表及其结构定义 (1)结构定义 顺序存储: 顺序表的元素按顺序存储在一块连续的内存区域中,每个元素占用相同大小的存储空间。通过数组实现,每个元素可以通过下标快速访问。 存储密度高: 因为顺序表使用…...
2.SQL注入-字符型
SQL注入-字符型(get) 输入kobe查询出现id和邮箱 猜测语句,字符在数据库中需要用到单引号或者双引号 select 字段1,字段2 from 表名 where usernamekobe;在数据库中查询对应的kobe,根据上图对应上。 select id,email from member where usernamekobe;编写payload语…...
在Ubuntu 14.04上安装和配置Elasticsearch的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 Elasticsearch 是一个用于实时分布式搜索和数据分析的平台。它因易用性、强大功能和可扩展性而备受欢迎。 Elasticsearch 支持 R…...
C++:inline关键字nullptr
inline关键字 C中inline使用关键点强调 (1)inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”,所以关键字 inline 必须与函数定义体放在一起,而不是和声明放在一起 (2)如果希望在多个c文件中使用,则inline函数应…...
数字信号处理实验三(IIR数字滤波器设计)
IIR数字滤波器设计(2学时) 要求: 产生一复合信号序列,该序列包含幅度相同的28Hz、50Hz、100Hz、150Hz的单音(单频)信号;其中,50Hz及其谐波为工频干扰(注:采样…...
天猫网站怎么做/宁波seo网站推广
Offer_day03_58 - II. 左旋转字符串 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"…...
最新网站建设常见问题/百度官网网址
目录1 UV动画1.1 滑动表面着色器1.2 让UV流动1.3 流动方向1.4 定向滑动2 无缝循环2.1 混合权重2.2 跷跷板2.3 时间偏移2.4 结合两个不同的扭曲2.5 UV跳跃2.6 分析跳跃3 动画调整3.1 平铺3.2 动画速度3.3 流动强度3.4 流偏移4 纹理化4.1 抽象水纹4.2 法线贴图4.3 导数贴图4.4 高…...
建设设计网站公司/营销策划公司经营范围
前两天机房c2机子的系统崩了,一直要研究重新装系统的事,虽然是才开始接触机房,但是有一点必须很清楚,学生机c盘绝对安装了不少学生的教学软件,关键是这些软件必须是版本一致,状态一致,那么如果自…...
东莞网站推广怎么做/潍坊seo建站
预计更新第一章. Python 简介 Python 简介和历史Python 特点和优势安装 Python 第二章. 变量和数据类型 变量和标识符基本数据类型:数字、字符串、布尔值等字符串操作列表、元组和字典 第三章. 控制语句和函数 分支结构:if/else 语句循环结构&#…...
微信小程序开发技术介绍/seo网站排名优化案例
目录缓冲区溢出的保护机制缓冲区溢出原理CANNARY(栈保护)FORTIFYNX(DEP)PIE(ASLR)RELRO检测工具checksec缓冲区溢出的保护机制 缓冲区溢出原理 缓冲区是内存中存放数据的地方。在程序试图将数据放到机器内存中的某一个位置的时候,因为没有足够的空间就会发生缓冲区溢…...
最好看的免费网站源码/网站排名软件
2019独角兽企业重金招聘Python工程师标准>>> 本文前戏较多,务实的同学可以直接跳到文末的结论。 由「钢的琴」网友脑洞大开延伸出了吉的他二的胡琵的琶,以及后来许嵩的「苏格拉没有底」,是否可以再拓展一下,得到哥本不…...