macOS Catalina(10.15.4)安装应用提示"无法打开"XXXX",因为无法验证开发者"的解决方法

macOS Catalina(10.15.4)使用`HomeBrew`安装`SageMath`:

$ brew cask install sage

启动的时候提示如下:

继续阅读macOS Catalina(10.15.4)安装应用提示"无法打开"XXXX",因为无法验证开发者"的解决方法

macOS Catalina(10.15.4)下RsaCtfTool的安装及使用

在CTF比赛中,往往会涉及到RSA解密类的题目,有了这个工具(基于python3.x)做起来就得心应手了。

这个也可以作为安全工具来使用,检查密钥的安全性。

$ git clone https://github.com/Ganapati/RsaCtfTool.git

$ cd RsaCtfTool

$ pip3 install -r "requirements.txt"

# 安装辅助数学计算库sagemath,提高计算效率
$ brew cask install sage

# 暴力破解RSA公钥,输出私钥
$ python3 RsaCtfTool.py --publickey certificate.crt --private

# 公钥中提取 N,e
$ python3 RsaCtfTool.py --publickey ~/certificate.crt --dumpkey
RSA简介

为了方便理解,先对RSA密钥体制做个简略的介绍。

  1. 选择两个大的参数,计算出模数 N = p * q
  2. 计算欧拉函数 φ = (p-1) * (q-1),然后选择一个e(1<e<φ),并且e和φ互质(互质:公约数只有1的两个整数)
  3. 取e的模反数d,计算方法为:e * d ≡ 1 (mod φ) (模反元素:如果两个正整数e和n互质,那么一定可以找到整数d,使得 e * d - 1 被n整除,或者说e * d被n除的余数是1。这时,d就叫做e的“模反元素”。欧拉定理可以用来证明模反元素必然存在。两个整数a,b,它们除以整数M所得的余数相等:a ≡ b(mod m),比如说5除3余数为2,11除3余数也为2,于是可写成11 ≡ 5(mod 3)。)
  4. 对明文m进行加密:c = pow(m, e, N),可以得到密文c。
  5. 对密文c进行解密:m = pow(c, d, N),可以得到明文m。
整理:

`p` 和 `q`:两个大的质数,是另一个参数N的的两个因子。
`N`:大整数,可以称之为模数
`e` 和 `d`:互为无反数的两个指数
`c` 和 `m`:密文和明文
`(N, e)`:公钥
`(N, d)`:私钥
`pow(x, y, z)`:效果等效`pow(x, y)% z`, 先计算`x`的`y`次方,如果存在另一个参数`z`,需要再对结果进行取模。
密钥长度:`n`以二进制表示的的位数,例如密钥长度为`512`代表`n`用二进制表示的长度为`512bit`。

RSA安全性分析

对于RSA加密算法,公钥`(N, e)`为公钥,可以任意公开,破解RSA最直接(亦或是暴力)的方法就是分解整数`N`,然后计算`欧拉函数φ(n)=(p-1) * (q-1)`,再通过`d * e ≡ 1 mod φ(N)`,即可计算出 `d`,然后就可以使用私钥`(N, d)`通过`m = pow(c,d,N)`解密明文。

保障RSA的安全性

1. 定期更换密钥
2. 不同的用户不可以使用相同的模数N
3. p与q的差值要大,最好是差几个比特
4. p-1与q-1都应该有大的素因子,一般建议选择的两个大素数p、q使得p=2p+1和q=2q+1也是素数
5. e的选择不要太小
6. d的选择也是不可以太小,最好满足d>=n的4分之1

参考链接


Android Studio 3.6.3/4.0/4.1/4.2配置Robolectric-3.8/4.3.1/4.5.1/4.6.1 Powermock-1.6.6单元测试环境

基础配置以及常见错误


目前版本的Android Studio 3.6.3/4.0/4.1/4.2使用Robolectric-3.8/4.3.1/4.5.1/4.6.1,只能配合Powermock-1.6.6,不能高于这个版本PowerMock ,尽管软件源中的版本已经更新升级到2.0.7版本了,但是Robolectric并没有及时更新依赖。尝试过使用最新版本的PowerMock,结果很多莫名的报错。

    // 单元测试
    testImplementation "com.android.support.test:runner:1.0.2"
    testImplementation "junit:junit:4.13.2"
    testImplementation "org.robolectric:robolectric:4.5.1"

    // 注意AndroidX环境下,不能引入shadows-supportv4,Jetifier转换的时候报错
    testImplementation "org.robolectric:shadows-supportv4:4.5.1"

    // MultiDex支持
    testImplementation "org.robolectric:shadows-multidex:4.5.1"
    
    // 此处版本更新需要特别小心,目前 robolectric 跟 powermock 存在兼容问题,
    // 需要固定的某些版本才能正常配合
    // 依赖关系参考 
    // https://github.com/robolectric/robolectric/wiki/Using-PowerMock
    testImplementation "org.powermock:powermock-module-junit4:1.6.6"
    testImplementation "org.powermock:powermock-module-junit4-rule:1.6.6"
    testImplementation "org.powermock:powermock-classloading-xstream:1.6.6"
    testImplementation "org.powermock:powermock-api-mockito:1.6.6"

如果 Windows 系统下出现如下提示,受限于Windows系统路径不能超过260个字符的限制

13:36 Error running 'xxxTest': Command line is too long. Shorten command line for xxxTest or also for Android JUnit default configuration.

貌似Windows 10 Build 14352版中已经可以通过修改注册表去除260字符的路径长度限制了。

在项目`/.idea/workspace.xml`文件中添加一行代码如下

<component name="PropertiesComponent">
    ...
    <property name="dynamic.classpath" value="true" />
</component>

对于使用MultiDex的应用,如果报告如下错误:

java.lang.RuntimeException: MultiDex installation failed (/var/folders/h6/4__l0pyn32j1mkkysynnxydr0000gn/T/robolectric-Method_xxxxxxxxxxxx_isCorrect4035485067136008322/com.xxxx.xxxx.app-sourceDir (Is a directory)).

	at android.support.multidex.MultiDex.install(MultiDex.java:121)
	at com.xxx.xx.app.xx.application.xxxxxx.attachBaseContext(MyApplication.java:212)
	at android.app.Application.attach(Application.java:212)
	at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:283)
	at org.robolectric.shadows.ShadowApplication.callAttach(ShadowApplication.java:79)
	at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:250)
	at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:169)
	at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:301)
	at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:243)
	at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

需要在`build.gradle`中引入

 
    // MultiDex支持
    testImplementation "org.robolectric:shadows-multidex:4.5.1"

例子测试代码:

package com.mobibrw.example;

import org.junit.Test;
import static org.junit.Assert.*;

import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.multidex.ShadowMultiDex;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(RobolectricTestRunner.class)
@PowerMockIgnore("jdk.internal.reflect.*")
@Config(shadows = ShadowMultiDex.class)
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() {
        assertEquals(4, 2 + 2);
    }
}

注意,需要

@Config(shadows = ShadowMultiDex.class)

才能使得配置生效。

如果发生如下错误:

java.lang.VerifyError: Expecting a stackmap frame at branch target 43
Exception Details:
  Location:
    com/meizu/cloud/pushsdk/base/IntentReceiver.onReceive(Landroid/content/Context;Landroid/content/Intent;)V @6: ifne
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: b200 08b6 0013 9a00 25bb 0004 5912 0110
    0x0000010: 0ab7 000e 59b3 000a b600 10bb 0003 59b2
    0x0000020: 000a b600 0fb7 000c b300 09b2 0009 bb00
    0x0000030: 0659 2a2b 2cb7 0011 b600 0d57 b1       


	at java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
	at java.lang.Class.getConstructor0(Class.java:3075)
	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
	at org.robolectric.util.ReflectionHelpers.callConstructor(ReflectionHelpers.java:396)
	at org.robolectric.internal.bytecode.ShadowImpl.newInstanceOf(ShadowImpl.java:18)
	at org.robolectric.shadow.api.Shadow.newInstanceOf(Shadow.java:35)
	at org.robolectric.android.internal.AndroidTestEnvironment.registerBroadcastReceivers(AndroidTestEnvironment.java:541)
	at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:265)
	at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:169)
	at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:301)
	at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:243)
	at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

继续阅读Android Studio 3.6.3/4.0/4.1/4.2配置Robolectric-3.8/4.3.1/4.5.1/4.6.1 Powermock-1.6.6单元测试环境

Synology(群晖)常见的配置项以及命令项

Apache2.2 相关配置与常见命令

# 目录相同链接位置 /usr/local/etc/apache22/conf/httpd22.conf
$ sudo vim /volume1/@appstore/Apache2.2/usr/local/etc/apache22/conf/httpd22.conf

# 重启 Apache2.2,有时候重启无效,此时请重启服务器
$ sudo /usr/syno/bin/synopkg restart httpd2.2

# 查看访问日志
$ sudo tail -f /var/log/httpd/apache22-access_log

# 查看错误日志
$ sudo tail -f /var/log/httpd/apache22-error_log

# DSM 7.x 查看错误日志
$ sudo tail -f /var/packages/Apache2.2/var/log/apache22-error_log

Apache2.4 相关配置与常见命令

# 目录相同链接位置 /usr/local/etc/apache24/conf/httpd24.conf
$ sudo vim /volume1/@appstore/Apache2.4/usr/local/etc/apache24/conf/httpd24.conf

# 重启 Apache2.4,有时候重启无效,此时请重启服务器
$ sudo /usr/syno/bin/synopkg restart httpd2.4

# 查看访问日志
$ sudo tail -f /var/log/httpd/apache24-access_log

# 查看错误日志
$ sudo tail -f /var/log/httpd/apache24-error_log

# DSM 7.x 查看错误日志
$ sudo tail -f /var/packages/Apache2.4/var/log/apache24-error_log

Nginx 相关配置与常见命令

# nginx 配置文件
$ sudo vim /etc/nginx/nginx.conf

# nginx 配置信息存储位置
$ sudo ls /usr/local/etc/nginx/conf.d

# 重启nginx
$ sudo synoservicecfg --restart nginx

# 查看日志
$ sudo tail -f /var/log/nginx/error.log

Web Station 相关配置与常见命令

# 默认网页服务器根目录

/volume1/web

继续阅读Synology(群晖)常见的配置项以及命令项

在macOS Catalina(10.15.4)安装ADB(Android调试桥)

什么是 ADB?

Android调试桥( adb )是一个开发工具,帮助安卓设备和个人计算机之间的通信。 这种通信大多是在USB电缆下进行,但是也支持Wi-Fi连接。 adb 还可被用来与电脑上运行的安卓模拟器交流通信。 adb 对于安卓开发来说就像一把“瑞士军刀”。

通过 Homebrew 安装

$ brew cask install android-platform-tools

测试是否正常安装

$ adb devices

手动安装

1、如果你以前安装过,请先删除老的文件

$ rm -rf ~/.android-sdk-macosx/

2、下载 android-sdk-macosx

下载地址:developer.android.com

3、将下载的文件解压并移动到 ~/.android-sdk-macosx

$ cd ~/Downloads(你的下载目录)/ 

$ unzip android-sdk*.zip 

$ mv android-sdk-macosx/ ~/.android-sdk-macosx

4、运行 SDK Manager

$ sh ~/.android-sdk-macosx/tools/android

5、根据你的需要选择,(我只需要Android SDK Platform-tools)[可选步骤]
6、选好后 Install
7、环境变量设置

$ echo 'export PATH=$PATH:~/.android-sdk-macosx/platform-tools/' >> ~/.bash_profile

8、更新配置文件

$ source ~/.bash_profile

9、测试是否正常安装

$ adb devices

参考链接


在 MAC OS X 安装 ADB (Android调试桥)

使用Python Openssl库解析X509证书信息

X.509 证书结构描述

常见的X.509证书格式包括:

后缀 作用
cer/crt 用于存放证书,它是2进制形式存放的,不含私钥
pem 以Ascii来表示,可以用于存放证书或私钥。
pfx/p12 用于存放个人证书/私钥,他通常包含保护密码,2进制方式。
p10 证书请求
p7r CA对证书请求的回复,只用于导入
p7b 以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥。

对于常见的https证书 一般是用crt或者pem来保存, http证书可点击网页前的锁按钮得到, 并且进行导出

继续阅读使用Python Openssl库解析X509证书信息

WordPress修改数据库返回数据

有个简单需求,就是 `Wordpress` 多个网站同步数据的情况下,根据网站域名的不同,修改数据库返回的数据。

实现这个的需求就是在当前 `Wordpress` 主题下的 `functions.php` 中实现 `the_post` 拦截函数,在数据库返回的数之后,进行替换。

例子如下:

function replace_serv_domain($post) {
    $local_addr = $_SERVER['SERVER_ADDR'];
    if ('10.105.114.251' == $local_addr) { 
        // 替换服务器的访问地址信息
        $post->post_content = str_ireplace('mobibrw.com', 'miniab.com', $post->post_content);
    }
    return $post;
}
add_action('the_post', 'replace_serv_domain');

这个替换过程只能针对没有使用 `WP Super Cache` 进行缓存的情况,如果已经使用 `WP Super Cache` 进行缓存,那么很可能导致没有及时生效。

如果只是需要替换域名,那么只需要在 wp-config.php 中定义 WP_HOME/WP_SITEURL 两个变量即可实现域名覆盖。

示例参考代码如下:

$HTTP_TYPE = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';   

$HOME = $HTTP_TYPE.$_SERVER['HTTP_HOST'].'/wordpress'; #获取当前访问的域名
$SIT_URL = $HTTP_TYPE.$_SERVER['HTTP_HOST'].'/wordpress';

#$HOME = $HTTP_TYPE.$_SERVER['HTTP_HOST'];
#$SIT_URL = $HTTP_TYPE.$_SERVER['HTTP_HOST'];	

define('WP_HOME', $HOME);
define('WP_SITEURL', $SIT_URL);

参考链接


Android Studio 3.6.2编译报错“GC overhead limit exceeded”

`Android Studio 3.6.2` 编译报错 “GC overhead limit exceeded”,详细的报错信息如下:

Problem in daemon expiration check
java.lang.OutOfMemoryError: GC overhead limit exceeded
	at org.gradle.cache.internal.DefaultFileLockManager$DefaultFileLock.<init>(DefaultFileLockManager.java:158)
	at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:110)
	at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:96)
	at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:91)
	at org.gradle.cache.internal.OnDemandFileAccess.readFile(OnDemandFileAccess.java:41)
	at org.gradle.cache.internal.SimpleStateCache.get(SimpleStateCache.java:49)
	at org.gradle.cache.internal.FileIntegrityViolationSuppressingPersistentStateCacheDecorator.get(FileIntegrityViolationSuppressingPersistentStateCacheDecorator.java:34)
	at org.gradle.launcher.daemon.registry.PersistentDaemonRegistry.getAll(PersistentDaemonRegistry.java:70)
	at org.gradle.launcher.daemon.registry.PersistentDaemonRegistry.getDaemonsMatching(PersistentDaemonRegistry.java:115)
	at org.gradle.launcher.daemon.registry.PersistentDaemonRegistry.getIdle(PersistentDaemonRegistry.java:83)
	at org.gradle.launcher.daemon.server.CompatibleDaemonExpirationStrategy.checkExpiration(CompatibleDaemonExpirationStrategy.java:54)
	at org.gradle.launcher.daemon.server.expiry.AllDaemonExpirationStrategy.checkExpiration(AllDaemonExpirationStrategy.java:46)
	at org.gradle.launcher.daemon.server.expiry.AnyDaemonExpirationStrategy.checkExpiration(AnyDaemonExpirationStrategy.java:43)
	at org.gradle.launcher.daemon.server.MasterExpirationStrategy.checkExpiration(MasterExpirationStrategy.java:73)
	at org.gradle.launcher.daemon.server.Daemon$DaemonExpirationPeriodicCheck.run(Daemon.java:269)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
	at java.lang.Thread.run(Thread.java:748)
org.gradle.internal.event.ListenerNotificationException: Failed to notify output event listener.
	at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:86)
	at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:325)
	at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:235)
	at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:141)
	at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy0.onOutput(Unknown Source)
	at org.gradle.internal.logging.sink.OutputEventTransformer.onOutput(OutputEventTransformer.java:104)
	at org.gradle.internal.logging.sink.OutputEventRenderer.onOutput(OutputEventRenderer.java:431)
	at org.gradle.internal.logging.sink.OutputEventListenerManager$1.onOutput(OutputEventListenerManager.java:36)
	at org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger.log(OutputEventListenerBackedLogger.java:160)
	at org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger.log(OutputEventListenerBackedLogger.java:152)
	at org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger.error(OutputEventListenerBackedLogger.java:504)
	at org.gradle.launcher.daemon.server.Daemon$DaemonExpirationPeriodicCheck.run(Daemon.java:274)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
Expiring Daemon because JVM heap space is exhausted
Daemon will be stopped at the end of the build after running out of JVM memory
Expiring Daemon because JVM heap space is exhausted

> Task :app:compileDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> GC overhead limit exceeded

这个问题是由于编译过程中的Java的内存开销太大超过了默认限制导致的,解决方法就是增大Java的内存限制。

具体操作为在项目的 `gradle.properties` 中修改内存限制 `org.gradle.jvmargs` 默认情况下,这个限制在 `1536m` 我们需要拉大到 `4096m`。

修改后的内容如下:

# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx4096m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

如果这个文件不存在,则在工程文件 `build.gradle` ,`gradlew` , `local.properties` 等相同的目录下新建 `gradle.properties` 这个文件即可。

参考链接


macOS Catalina(10.15.4)/IntelliJ IDEA 2018.3/Tomcat 9.0.33/Maven项目调试报错"Caused by: java.util.zip.ZipException: zip file is empty"

macOS Catalina(10.15.4)/IntelliJ IDEA 2018.3/Tomcat 9.0.33/Maven项目调试时报错,这个项目以前是可以正常调试的,一段时间之后,就不能正常调试之下了

继续阅读macOS Catalina(10.15.4)/IntelliJ IDEA 2018.3/Tomcat 9.0.33/Maven项目调试报错"Caused by: java.util.zip.ZipException: zip file is empty"