Android Proguard混淆

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

目录

  • 一、导读
  • 二、概览
  • 三、语法规则
    • 3.1 输入/输出选项
    • 3.2 保留选项
    • 3.3 缩小选项
    • 3.4 优化选项
    • 3.5 混淆选项
    • 3.6 预验证选项
    • 3.7 常规选项
  • 四、过滤器
    • 4.1 增量混淆
    • 4.2 寻找未使用的代码及方法等(废弃代码)
  • 五、混淆基本原则
    • 5.1 系统相关类不要混淆
    • 5.2 部分项目相关类不要混淆
    • 5.3、添加混淆字典
    • 5.4 r8 & proguard
  • 六、 推荐阅读

在这里插入图片描述

一、导读

我们继续总结学习基础知识,温故知新。
本文讲述Android Proguard 相关知识。

二、概览

Proguard 四部曲:
shrink(删减):删减无用代码,包括类、变量、方法和属性,缩减了APK包的大小

optimize(优化):优化方法字节码,并移除无用的构造方法

obfuscate(混淆):混淆现有代码,将有意义的命名替换为无意义的命名

preverify(预校验):给类添加预校验信息,这是J2ME和Java 6及以上要求的

proguard 文档

三、语法规则

3.1 输入/输出选项

 @ filename

“文件名”的缩写 ‘-include filename’.

 -include filename

从给定文件filename递归读取配置选项

 -basedirectory directoryname

指定这些配置参数或此配置文件中所有后续相对文件名的基目录

 -injars class_path

指定要处理的应用程序的输入 jar(或 apks、aabs、aars、wars、ears、jmods、zip 或目录)。
可以使用多个-injars选项指定类路径条目。

-outjars class_path

指定输出 jar 的名称(或 apks、aabs、aars、wars、ears、jmods、zips 或目录)。
为了更好的可读性,可以使用多个-outjars选项指定类路径条目。如果没有任何-outjars选项,则不会编写任何 jars

-libraryjars class_path

指定要处理的应用程序的库 jar(或 apks、aabs、aars、wars、ears、jmods、zips、目录)

-skipnonpubliclibraryclasses

指定在读取库 jar 时跳过非公共类,以加快处理速度并减少 ProGuard 的内存使用量

-dontskipnonpubliclibraryclasses

指定不忽略非公共库类。从版本 4.5 开始,这是默认设置

-dontskipnonpubliclibraryclassmembers

指定不忽略包可见的库类成员(字段和方法)

-keepdirectories [directory_filter]

指定要保留在输出 jar 中的目录(或 apks、aabs、aars、wars、ears、jmods、zips 或目录)

-target version

已弃用:此选项仅适用于 Java 类文件版本 <= 11

-forceprocessing

指定处理输入,即使输出看起来是最新的

3.2 保留选项


-keep [,modifier,...] class_specification
-keepnames class_specification
指定要保留为代码入口点的类和类成员(字段和方法)-keepclassmembers [,modifier,...] class_specification
-keepclassmembernames class_specification
指定要保留的类成员(如果它们的类也被保留)-keepclasseswithmembers [,modifier,...] class_specification
-keepclasseswithmembernames class_specification
指定要保留的类和类成员,前提是所有指定的类成员都存在
-if class_specification

指定必须present激活后续保留选项(-keep、-keepclassmembers、…)的类和类成员。
条件和后续的 keep 选项可以共享通配符和对通配符的引用。例如,您可以使用Dagger和Butterknife等框架保留类,前提是项目中存在具有相关名称的类。

-printseeds [filename]

指定详尽列出与各种-keep选项匹配的类和类成员。该列表将打印到标准输出或给定文件。该列表可用于验证是否确实找到了预期的类成员,
特别是在您使用通配符时。例如,您可能想要列出您保留的所有应用程序或所有小程序。

3.3 缩小选项

-dontshrink

指定不收缩输入。默认情况下,ProGuard 会缩小代码:它会删除所有未使用的类和类成员。它只保留各种-keep选项列出的选项以及它们直接或间接依赖的选项。
它还在每个优化步骤之后应用收缩步骤,因为某些优化可能会提供删除更多类和类成员的可能性。

-printusage [filename]

指定列出输入类文件的死代码。该列表将打印到标准输出或给定文件。例如,您可以列出应用程序未使用的代码。仅适用于收缩时。

-whyareyoukeeping class_specification

指定打印有关为何给定类和类成员保留在收缩步骤中的详细信息。如果您想知道为什么某些给定元素出现在输出中,这可能很有用。

3.4 优化选项

-dontoptimize

指定不优化输入类文件。默认情况下,ProGuard 会优化所有代码。它内联和合并类和类成员,并在字节码级别优化所有方法。

-optimizations optimization_filter

以更细粒度的级别指定要启用和禁用的优化。仅适用于优化时
例如:

# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-optimizationpasses n

指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。)

-assumenosideeffects class_specification

指定除了可能返回值之外没有任何副作用的方法。例如,该方法System.currentTimeMillis()返回一个值,但它没有任何副作用。
在优化步骤中,如果 ProGuard 可以确定未使用返回值,则可以删除对此类方法的调用。ProGuard 会分析您的程序代码以自动查找此类方法。
它不会分析库代码,因此此选项很有用。例如,您可以指定 method System.currentTimeMillis(),以便删除对其的任何空闲调用。如果小心的话,
您还可以使用该选项来删除日志记录代码。请注意,ProGuard 将该选项应用于指定方法的整个层次结构。仅适用于优化时。一般来说,做出假设可能是危险的。
您可以轻松地破坏已处理的代码。仅当您知道自己在做什么时才使用此选项!

-assumenoexternalsideeffects class_specification
-assumenoescapingparameters class_specification
-assumenoexternalreturnvalues class_specification
-assumevalues class_specification
-allowaccessmodification
-mergeinterfacesaggressively
-optimizeaggressively

代码优化相关,用不好容易出问题。

3.5 混淆选项

-dontobfuscate

指定不混淆输入类文件。默认情况下,ProGuard 会混淆代码:它为类和类成员分配新的短随机名称。它删除了仅对调试有用的内部属性,例如源文件名、变量名和行号。

-printmapping [filename]

指定打印已重命名的类和类成员从旧名称到新名称的映射。映射被打印到标准输出或给定文件。例如,后续增量混淆需要它,或者如果您想再次理解混淆的堆栈跟踪。仅在混淆时适用。

-applymapping filename

指定重用在 ProGuard 的先前混淆运行中打印出的给定名称映射。映射文件中列出的类和类成员接收与其一起指定的名称。未提及的类和类成员将获得新名称。
该映射可以引用输入类以及库类。此选项对于增量混淆非常有用,即处理现有代码片段的附加组件或小补丁。如果代码结构发生根本性变化,ProGuard 可能会打印出应用映射导致冲突的警告。
您可以通过-useuniqueclassmembernames在两次混淆运行中指定该选项来降低这种风险。只允许使用单个映射文件。仅在混淆时适用。

-obfuscationdictionary          proguard-dic.txt  //指定一个字典文件作为混淆字典
-classobfuscationdictionary     proguard-dic.txt //类字典
-packageobfuscationdictionary   proguard-dic.txt //包字典
-overloadaggressively

指定在混淆时应用积极的重载。然后,多个字段和方法可以获得相同的名称,只要它们的参数和返回类型不同,如 Java 字节码所要求的(不仅仅是它们的参数,如 Java 语言所要求的)。
此选项可以使处理后的代码更小(并且更难以理解,大小,体积)。仅在混淆时适用。

但是可能存在问题,如Google 的 Dalvik VM 无法处理过载的静态字段。

-useuniqueclassmembernames

指定将相同的混淆名称分配给具有相同名称的类成员,并将不同的混淆名称分配给具有不同名称的类成员(对于每个给定的类成员签名)。如果没有该选项,更多的类成员可以映射到相同的短名称,如“a”、“b”等。因此,
该选项会稍微增加结果代码的大小,但它确保保存的混淆名称映射始终可以在后续增量混淆步骤中受到尊重

-dontusemixedcaseclassnames

指定在混淆时不生成大小写混合的类名。默认情况下,混淆的类名可以包含大写字符和小写字符的混合。

-keeppackagenames [package_filter]

指定不混淆给定的包名称。

-flattenpackagehierarchy [package_name]

指定通过将重命名的所有包移动到单个给定父包中来重新打包它们。如果不带参数或使用空字符串 (‘’),包将移至根包中。此选项是进一步混淆包名称的示例之一。它可以使处理后的代码更小且更难以理解(大小,体积)。仅在混淆时适用。

与 repackageclasses 冲突

-repackageclasses [package_name]

指定通过将重命名的所有类文件移动到单个给定包中来重新打包它们。如果没有参数或使用空字符串 (‘’),则包将被完全删除。该选项会覆盖该-flattenpackagehierarchy选项。这是进一步混淆包名称的另一个例子。
它可以使处理后的代码变得更小并且更难以理解(大小,体积)。它的已弃用名称是-defaultpackage. 仅在混淆时适用。

-keepattributes [attribute_filter]

指定要保留的任何可选属性。可以使用一个或多个指令来指定属性-keepattributes

# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
# 保护代码中的Annotation不被混淆
-keepattributes *Annotation*
# 避免混淆泛型, 这在JSON实体映射时非常重要
-keepattributes Signature
-keepparameternames

指定保留所保留方法的参数名称和类型。该选项实际上保留了调试属性LocalVariableTable和LocalVariableTypeTable

-renamesourcefileattribute [string]

指定要放入类文件的SourceFile属性(和属性)中的常量字符串。SourceDir请注意,该属性必须首先存在,因此还必须使用-keepattributes指令显式保留它。
例如,您可能希望让经过处理的库和应用程序生成有用的模糊堆栈跟踪。仅在混淆时适用。

-keepkotlinmetadata

已弃用:使用-keep class kotlin.Metadata替代。指定处理kotlin.Metadata注释(如果存在)。目前仅支持对其内容进行缩小和混淆。如果启用此选项,则应从优化中排除包含此类注释的类。

-adaptclassstrings [class_filter]

指定与类名相对应的字符串常量也应该被混淆。如果没有过滤器,所有与类名相对应的字符串常量都会被调整。

-adaptresourcefilenames [file_filter]

根据相应类文件(如果有)的混淆名称指定要重命名的资源文件。如果没有过滤器,则与类文件对应的所有资源文件都会被重命名。

-adaptresourcefilecontents [file_filter]

指定要更新内容的资源文件和本机库。资源文件中提到的任何类名都会根据相应类(如果有)的混淆名称进行重命名。

3.6 预验证选项

-dontpreverify

指定不对已处理的类文件进行预验证。

-microedition

指定处理的类文件针对 Java Micro Edition。

-android

指定处理的类文件是针对Android平台的

3.7 常规选项

-verbose

指定在处理过程中写出更多信息。如果程序因异常而终止,此选项将打印出整个堆栈跟踪,而不仅仅是异常消息。

-dontnote [class_filter]

指定不打印有关配置中潜在错误或遗漏的注释,例如类名称中的拼写错误或缺少可能有用的选项。可选的过滤器是正则表达式;ProGuard 不会打印有关具有匹配名称的类的注释。

-dontwarn [class_filter]

指定根本不警告未解决的引用和其他重要问题。可选的过滤器是正则表达式;ProGuard 不会打印有关具有匹配名称的类的警告。忽视警告可能会很危险。

-ignorewarnings

指定打印有关未解决的引用和其他重要问题的任何警告,但在任何情况下都继续处理。忽视警告可能会很危险。屏蔽警告

-printconfiguration [filename]

指定写出已解析的整个配置,包括包含的文件和替换的变量。该结构被打印到标准输出或给定文件。

-dump [filename]

指定在任何处理之后写出类文件的内部结构。该结构被打印到标准输出或给定文件。

-addconfigurationdebugging

指定使用调试语句来检测已处理的代码,这些调试语句会打印出缺少 ProGuard 配置的建议。

四、过滤器

?	匹配名称中的任何 单个 字符。  例如,“ com.example.Test?”匹配“ com.example.Test1”和“ com.example.Test2”,但不匹配“ com.example.Test12”。*	匹配名称中不包含包分隔符或目录分隔符的任何部分。 
例如,“ com.example.*Test*”匹配“ com.example.Test”和“ com.example.YourTestApplication”,但不匹配“ com.example.mysubpackage.MyTest”。
或者,更一般地说,“ com.example.*”匹配“ com.example”中的所有类,但不匹配其子包中的所有类。**	匹配名称的任何部分,可能包含任意数量的包分隔符或目录分隔符。<n>	匹配同一选项中第n个匹配的通配符。例如,“ com.example.*Foo<1>”匹配“ com.example.BarFooBar”。
例如,“ java/**.class,javax/**.class”匹配 和 中的所有类java文件javax。此外,文件名前面可以有感叹号“ ! ” '从进一步尝试与后续文件名匹配中排除该文件名。例如,“ !**.gif,images/**”匹配images目录中除 gif 文件之外的所有文件。忽略输入 jar 中的某些文件,images此配置会删除该目录及其子目录中的所有文件。
-injars  in.jar(!images/**)
-outjars out.jar仅保留第一个输入 jar 中的清单文件:
-injars  in1.jar
-injars  in2.jar(!META-INF/MANIFEST.MF)
-injars  in3.jar(!META-INF/MANIFEST.MF)
-outjars out.jar
例如,“ foo,*bar”匹配名称foo以及所有以 结尾的名称bar。
<init>	匹配任何构造函数。
<fields>	匹配任何字段。
<methods>	匹配任何方法。
*	匹配任何字段或方法。

通配符	意义
%	匹配任何原始类型(" boolean"、" int" 等)或 " void" 类型。
?	匹配类名中的任何单个字符。
*	匹配类名中不包含包分隔符的任何部分。
**	匹配类名的任何部分,可能包含任意数量的包分隔符。
***	匹配任何类型(原始或非原始、数组或非数组)。
...	匹配任意数量任意类型的参数。
<n>	匹配同一选项中第n个匹配的通配符。

请注意?,、 和通配符永远不会匹配原始类型。此外,只有通配符才能匹配任何维度的数组类型。例如,“ ** get*()”匹配“ java.lang.Object getObject()”,
但不匹配“ float getFloat()”,也不匹配“ java.lang.Object[] getObjects()”。

4.1 增量混淆

-injars       proguardgui.jar
-outjars      proguardgui_out.jar
-injars       proguard.jar
-outjars      proguard_out.jar
-libraryjars  <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
-applymapping proguard.map-keep public class proguard.gui.ProGuardGUI {public static void main(java.lang.String[]);
}

4.2 寻找未使用的代码及方法等(废弃代码)


#不进行优化,建议使用此选项,
-dontoptimize
#指定不混淆输入类文件。默认情况下,ProGuard 会混淆代码:它为类和类成员分配新的短随机名称。它删除了仅对调试有用的内部属性,例如源文件名、变量名和行号。
-dontobfuscate# 不进行预校验,Android不需要,可加快混淆速度。
-dontpreverify
#指定列出输入类文件的死代码。该列表将打印到标准输出或给定文件。例如,您可以列出应用程序未使用的代码。仅适用于收缩时。
-printusage

点击build后,可以看到如下的输出,列出了几个没有使用到的类及方法


> Task :app:minifyReleaseWithR8
org.fmod.example.CallBack
org.fmod.example.CallBackManager
org.fmod.example.DeadClass
org.fmod.example.MemoryShakeActivity:public void dpOperate()public void testa()public void testb()
org.fmod.example.BuildConfig
org.fmod.example.R$color
org.fmod.example.R$drawable
org.fmod.example.R$id
org.fmod.example.R$layout
org.fmod.example.R$mipmap
org.fmod.example.R$string
org.fmod.example.R$style
org.fmod.example.R$xml
org.fmod.example.R
org.fmod.example.databinding.ActivityMemoryBinding:public final android.widget.Button btMemoryprivate void <init>(android.widget.FrameLayout,android.widget.Button)public static org.fmod.example.databinding.ActivityMemoryBinding bind(android.view.View)public static org.fmod.example.databinding.ActivityMemoryBinding inflate(android.view.LayoutInflater)public static org.fmod.example.databinding.ActivityMemoryBinding inflate(android.view.LayoutInflater,android.view.ViewGroup,boolean)
androidx.core.location.LocationManagerCompat$$InternalSyntheticLambda$1$196e0315f48caa68131c5d4d780ff53e9618a06658f902ea94f753d0df163305$1
androidx.core.location.LocationManagerCompat:public static synthetic java.lang.Boolean $r8$lambda$JLIcm4BkQpukCiUbhX4BKZUICt4(android.location.LocationManager,androidx.core.location.LocationManagerCompat$GpsStatusTransport)

#不进行优化,建议使用此选项,
-dontoptimize
#指定不混淆输入类文件。默认情况下,ProGuard 会混淆代码:它为类和类成员分配新的短随机名称。它删除了仅对调试有用的内部属性,例如源文件名、变量名和行号。
-dontobfuscate# 不进行预校验,Android不需要,可加快混淆速度。
-dontpreverify
#指定列出输入类文件的死代码。该列表将打印到标准输出或给定文件。例如,您可以列出应用程序未使用的代码。仅适用于收缩时。
-printusage-keep public class org.fmod.example.DeadClass {public static void main(java.lang.String[]);
}

如果我们将某一个未使用的class 进行keep,则结果如下


> Task :app:minifyReleaseWithR8
org.fmod.example.BuildConfig
org.fmod.example.CallBack
org.fmod.example.CallBackManager
org.fmod.example.DeadClass:public void testa()public void testb()public void testc()
org.fmod.example.MemoryShakeActivity:public void dpOperate()public void testa()public void testb()
org.fmod.example.R$color
org.fmod.example.R$drawable
org.fmod.example.R$id
org.fmod.example.R$layout
org.fmod.example.R$mipmap
org.fmod.example.R$string
org.fmod.example.R$style
org.fmod.example.R$xml
org.fmod.example.R
org.fmod.example.databinding.ActivityMemoryBinding:public final android.widget.Button btMemoryprivate void <init>(android.widget.FrameLayout,android.widget.Button)public static org.fmod.example.databinding.ActivityMemoryBinding bind(android.view.View)public static org.fmod.example.databinding.ActivityMemoryBinding inflate(android.view.LayoutInflater)public static org.fmod.example.databinding.ActivityMemoryBinding inflate(android.view.LayoutInflater,android.view.ViewGroup,boolean)
androidx.core.location.LocationManagerCompat$$InternalSyntheticLambda$1$196e0315f48caa68131c5d4d780ff53e9618a06658f902ea94f753d0df163305$1
androidx.core.location.LocationManagerCompat:public static synthetic java.lang.Boolean $r8$lambda$JLIcm4BkQpukCiUbhX4BKZUICt4(android.location.LocationManager,androidx.core.location.LocationManagerCompat$GpsStatusTransport)

五、混淆基本原则

项目中以下类不应该混淆

5.1 系统相关类不要混淆

  • 四大组件:如 Activity、Service、Provider、Broadcast及其Fragment等系统相关类
#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends androidx.fragment.app.Fragment
-keep public class * extends android.content.ContentProvider
  • view(WebView)相关类
-keepclassmembers class * extends android.app.Activity{public void *(android.view.View);
}
#不混淆任何一个View中的setXxx()getXxx()方法,
#因为属性动画需要有相应的setter和getter的方法实现
-keep public class * extends android.view.View{*** get*();void set*(***);public <init>(android.content.Context);public <init>(android.content.Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSet, int);
}
  • 枚举类
#不混淆枚举中的values()valueOf()方法
-keepclassmembers enum * {public static **[] values();public static ** valueOf(java.lang.String);
}
  • 注解
  • support下的所有类及其内部类

-keep class android.support.** {*;}## 保留support下的所有类及其内部类
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
  • Serializable
# 继承Serizalizable的类的如下成员不被移除混淆
-keepclassmembers class * implements java.io.Serializable {java.lang.Object writeReplace();java.lang.Object readResolve();static final long serialVersionUID;private static final java.io.ObjectStreamField[] serialPersistentFields;private void writeObject(java.io.ObjectOutputStream);private void readObject(java.io.ObjectInputStream);
}
  • Parcelable的子类和Creator静态成员变量

#不混淆Parcelable实现类中的CREATOR字段,
-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;
}

5.2 部分项目相关类不要混淆

  • 数据模型(各种数据模型类,GSON、fastjson等框架解析服务端数据时,混淆后解析不了)
-keep class com.xxx.entity.** {*;}
  • Jni接口和java的native方法 (这个方法需要和native方法保持一致,混淆后找不到会报错)
-keepclasseswithmembernames class * {native <methods>;
}
  • Java接口 (主要针对对外开放的接口)

  • 调用反射的地方 ()

  • 抽象内部类
    比如Animal的内部类不混淆

-keep class com.xxx.demo.Animal{*;}
-keep class com.xxx.demo.Animal$*{*;}
  • 使用到的第三方开源库或者引用其他第三方的SDK包
# 微信支付 
-keep class com.tencent.mm.opensdk.** {*; }
  • AOP或者读取路径等的地方

整理了一个基础混淆文件:
Android通用混淆文件

5.3、添加混淆字典

为了是混淆更混乱,可以添加自定义的混淆字典
-classobfuscationdictionary proguard-dic.txt //类字典
-obfuscationdictionary proguard-dic.txt //混淆字典
-packageobfuscationdictionary proguard-dic.txt //包字典

混淆字典下载地址

5.4 r8 & proguard

如果不想用R8,想用回ProGuard的话,可以在gradle.properties文件中添加下述配置禁用R8:

android.enableR8=falseandroid.enableR8.libraries=false

Android在打包后,一般会有以下几个文件:
mapping.txt、usage.txt 等

mapping.txt→ 原始与混淆过的类、方法、字段名称间的转换关系;seeds.txt→ 未进行混淆的类与成员;usage.txt→ APK中移除的代码;即废弃代码configuration.txt→ missing_rules.txtresources.txt→ 资源优化记录文件,哪些资源引用了其他资源,哪些资源在使用,哪些资源被移除;

参考

proguard 文档

六、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

未经允许不得转载
ddd

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/146245.shtml

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

相关文章

系统韧性研究(5)| 常用的系统韧性技术

如果不利事件或条件导致系统无法正常运行&#xff0c;则它们可能会对有价值的资产造成各种形式的损害。正如我在本系列的前几篇文章中概述的那样&#xff0c;系统韧性很重要&#xff0c;因为没有人想要一个无法克服“不可避免的逆境”的脆弱系统。 在本系列的第一篇文章中&…

36、Flink 的 Formats 之Parquet 和 Orc Format

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

人生阶段总结

--回顾一下我迷茫、努力、不开心又失败的阶段人生自我介绍一下&#xff0c;我是一个智力平平&#xff0c;记忆力差&#xff0c;适合自学的长睡眠者。 大专之前 国内的应试教育基本上不适合我&#xff0c;厌恶补课厌恶机械式听课刷题&#xff0c;所有的优势学科都是自学&#xf…

eclipse启动无法找到类(自定义监听器)

一.报错 二.排查 1.首先检查代码是否有问题 本人报错是找不到监听器&#xff0c;故检查监听器的代码和web.xml文件是否有问题 public class DoorListener implements ServletContextListener 监听器是否继承并实现ServletContextListener中的方法。 web.xml中&#xff1a; &…

EMP.DLL是什么东西?怎么解决EMP.DLL文件缺失

在我们使用电脑的过程中&#xff0c;有时会遇到一些特定的错误提示&#xff0c;比如“emp.dll文件缺失”。这样的提示对许多用户来说可能一脸懵逼&#xff0c;不知道怎么处理&#xff0c;那么&#xff0c;究竟什么是emp.dll&#xff1f;它的缺失会产生什么影响&#xff1f;又应…

阿里云CentOS主机开启ipv6

目录 一、云主机开启和使用 ipv6 1、网络和交换机开启 ipv6 2、创建 / 编辑云主机&#xff0c;开启ipv6 3、安全组放行ipv6端口 二、使用 ipv6 地址进行 ssh 连接 三、ipv6 地址绑定域名 一、云主机开启和使用 ipv6 1、网络和交换机开启 ipv6 进入网络、交换机详情页面…

ClickHouse的分片和副本

1.副本 副本的目的主要是保障数据的高可用性&#xff0c;即使一台ClickHouse节点宕机&#xff0c;那么也可以从其他服务器获得相同的数据。 Data Replication | ClickHouse Docs 1.1 副本写入流程 1.2 配置步骤 &#xff08;1&#xff09;启动zookeeper集群 &#xff08;2&…

最新自动定位版本付费进群系统源码

更新内容&#xff1a; 1.在网站首页增加了付款轮播功能。 2.新增了城市定位功能&#xff0c;方便用户查找所在城市的相关信息。 3.对域名库及支付设置进行了更新和优化。 4.增加了一种图模板设置模式&#xff0c;简化了后台模板设置流程。 5.此外还进行了前后台的其他优化…

蓝桥杯第三周算法竞赛D题E题

发现更多计算机知识&#xff0c;欢迎访问Cr不是铬的个人网站 D迷宫逃脱 拿到题目一眼应该就能看出是可以用动态规划来解决。但是怎么定义dp呢? 这个题增加难度的点就在当所在位置与下一个要去的位置互质的时候&#xff0c;会消耗一把钥匙。当没有钥匙的时候就不能移动了。想…

Linux(3):Linux 的文件权限与目录配置

把具有相同的账户放入到一个组里面&#xff0c;这个组就是这两个账户的 群组 。在访问资源&#xff08;操作系统中计算机的资源&#xff09;时&#xff0c;可以让这个组里面的所有用户都具有访问权限。 每个账号都可以有多个群组的支持。 在我们Liux 系统当中&#xff0c;默认的…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 4》(8)

《Linux操作系统原理分析之Linux 进程管理 4》&#xff08;8&#xff09; 4 Linux 进程管理4.4 Linux 进程的创建和撤销4.4.1 Linux 进程的族亲关系4.4.2 Linux 进程的创建4.4.3 Linux 进程创建的过程4.4.4 Linux 进程的执行4.4.5 Linux 进程的终止和撤销 4 Linux 进程管理 4.…

Redis - 订阅发布替换 Etcd 解决方案

为了减轻项目的中间件臃肿&#xff0c;由于我们项目本身就应用了 Redis&#xff0c;正好 Redis 的也具备订阅发布监听的特性&#xff0c;正好应对 Etcd 的功能&#xff0c;所以本次给大家讲解如何使用 Redis 消息订阅发布来替代 Etcd 的解决方案。接下来&#xff0c;我们先看 R…

vue2项目修改编译巨慢

前言&#xff1a;我们的一个vue项目在给新同事后他说编译贼慢&#xff0c;一个小修改项5分钟才能自动编译成功&#xff0c;我把项目放到新电脑上也巨慢&#xff0c;升级了nodejs好使了一些&#xff0c;但还是慢&#xff0c;最后引入webpack后巨快&#xff0c; 在项目的package…

redis实战篇(2)

优惠卷秒杀 通过本章节&#xff0c;我们可以学会Redis的计数器功能&#xff0c; 结合Lua完成高性能的redis操作&#xff0c;同时学会Redis分布式锁的原理&#xff0c;包括Redis的三种消息队列 3、优惠卷秒杀 3.1 -全局唯一ID 每个店铺都可以发布优惠券&#xff1a; 当用户抢…

linux课程第一课------命令的简单的介绍

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

内网离线安装elasticsearch、kibana

一、软件获取 elastic kibana 二、elastic安装 解压安装即可提前可改下配置文件&#xff0c;不然可能会出现内存分配错误 三、运行elastic 需要调试看信息的话&#xff0c;可在cmd窗口运行bat&#xff0c;就会打印输出信息了。 生产kibana token bin\elasticsearch-create…

交换机如何配置BGP协议

环境&#xff1a; 华为交换机 华三交换机 问题描述&#xff1a; 交换机如何配置BGP协议 解决方案&#xff1a; 华三交换机上配置案例 1.配置BGP协议&#xff0c;可以按照以下步骤进行&#xff1a; 登录交换机&#xff1a;使用SSH、Telnet或控制台等方式登录到华三交换…

简单理解路由重分发(用两路由器来理解)

相关命令&#xff1a; default-information originate //*重分发默认路由 redistribute rip subnets //*重分发rip redistribute ospf 1 metric 3 //*重分发ospf&#xff08;其中&#xff1a;1是ospf进程id 3是跳数&#xff09; redistribute sta…

main.js 中的 render函数

按照之前的单组件文件中的写法&#xff0c;我们的写法应该是这样的 import App from ./App.vuenew Vue({el: #app,templete: <App></App>,components: {App}, }) 1、定义el根节点。2、注册App组件。3、渲染 templete 模板 但是在脚手架工程中&#xff0c;他是这…

Java 之拼图小游戏

声明 此项目为java基础的阶段项目,此项目涉及了基础语法,面向对象等知识,具体像语法基础如判断,循环,数组,字符串,集合等…; 面向对象如封装,继承,多态,抽象类,接口,内部类等等…都有涉及。此项目涉及的内容比较多,作为初学者可以很好的将前面的知识串起来。此项目拿来练手以及…