Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

ProGuard学习笔记

13
Nov
2015

ProGuard学习笔记

By Alex
/ in Java
2 Comments
ProGuard简介

ProGuard是一个开源的Java类文件(.class)处理工具,相比起其它的Java混淆器,ProGuard更快,更易用。它同时提供了命令行和图形界面。ProGuard能够:

  1. 压缩(Shrunk ):检测未使用的类、字段、方法、属性,并移除
  2. 优化(Optimization):分析并优化方法的字节码,可以进行多步骤的优化
  3. 混淆(Obfuscation ):重命名类、字段、方法,使用更短且无意义的名字
  4. 预校验(Preverification ):为字节码添加预校验信息,预校验信息对Java 6+是需要的

上述功能可以单独使用,也可以在一次调用中按照下面的步骤一次性完成:Proguard-process

作为ProGuard输入的可以是jar、war、ear、zip、apk或者目录,经过最终处理后,输出到相应的压缩文件或者目录中。需要注意的是,输入文件可以包含资源文件,其名称和内容会被更新,以反映被混淆后的类名。

你需要为ProGuard指定库文件(lib jars),这些库用来编译被处理的那些类,这些库不会被改变。

入口点(Entry points)

为了判断哪些代码必须保留,那些可以被删除或者混淆,你需要为ProGuard指定“入口点”。入口点是一些类,它们通常是Main classes、methods、applets、activities,等等。ProGuard按如下规则使用入口点:

  1. 在压缩阶段:从入口点开始,递归的判断哪些类、类成员被使用,所有其它的则被丢弃
  2. 在优化阶段:非入口点函数或者方法,可能被设置为private、static、final、未使用的参数可能被移除,某些方法可能被内联
  3. 在混淆阶段:非入口点类、类成员被重命名
  4. 预校验阶段不需要知道入口点信息
反射的处理

反射和内省机制为ProGuard的处理带来困难,被动态创建(例如 Class.forName() )或者动态调用(根据字符串名称通过反射)的类/方法,必须作为入口点声明。在大量使用反射、基于配置文件的应用中(例如SSH框架),基本上不可能自动判断哪些类可以被保留,你需要在配置文件中使用 -keep 选项。

尽管如此,ProGuard能够自动识别并处理以下反射调用:

  1. Class.forName("SomeClass")
  2. SomeClass.class
  3. SomeClass.class.getField("someField")
  4. SomeClass.class.getDeclaredField("someField")
  5. SomeClass.class.getMethod("someMethod", new Class[] {})
  6. SomeClass.class.getMethod("someMethod", new Class[] { A.class })
  7. SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
  8. SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
  9. SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
  10. SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
  11. AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
  12. AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
  13. AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")

这些调用中引用的类、类成员不会被删除,如果执行混淆,它们会自动引用混淆后的名称。

ProGuard用法和选项

命令格式如下:

Shell
1
2
3
java -jar proguard.jar
    @myconfig.pro   #配置文件提供的选项
    -verbose        #命令行提供的选项

支持通过配置文件提供选项,配置文件中的注释以#开始。选项中,文件名具有空格的,必须使用引号包含。 

输入/输出选项
 选项 说明 
@filename 等价于-include filename,从文件中读取配置选项
-basedirectory dir 指定后面所有选项中,相对路径的基准目录
-injars classpath 指定需要处理的压缩包(各种ar)或者目录。其中的文件会被处理,并输出到-outjars指定的文件中。对于资源文件,默认不做修改的拷贝,可以使用过滤器选项对文件进行过滤。该选项可以出现多次
-outjars classpath 指定输出压缩包或者目录,在此选项之前的所有-injars中的文件,都被输出到该选项指定的文件。可以使用过滤器选项对文件进行过滤
-libraryjars classpath 指定输入所依赖的库,至少要包含输入类锁继承的那些类,仅仅被调用的类则不需要包含(但是包含了可以提升优化效果)。需要注意的是,程序使用的运行时库需要明确指定(例如rt.jar)
-skipnonpubliclibraryclasses 是否跳过依赖库中非public类,默认不跳过,跳过可以提升性能,因为库的非公共类一般与程序无关
-dontskipnonpubliclibraryclasses 不跳过依赖库中的非public类,4.5+默认值
-dontskipnonpubliclibraryclassmembers 不跳过包可见的依赖库类成员(字段、方法),通常依赖库中的default 成员与程序无关,但是某些程序可能刻意的把自己的包名弄得和依赖库一样
-keepdirectories filter 指定在输出文件中保留的目录,如果不指定过滤器,则所有目录都保持。默认情况下所有目录都被移除
-target version 指定输出class的版本,默认保持和输入版本一致。如果提高版本,则需要预校验;一般不能降低版本,因为低版本可能不支持某些构造
-forceprocessing 强制处理,即使输出文件已经是最新的(up to date)
保留选项

注意选项的命名规律:-keep*用于防止目标被移除或者重命名、-keep*names则仅仅用于防止重命名。

选项 说明
-keep -keep [,modifier,...] class_spec 作为入口点保留的类、类成员。对于库,所有公共成员都需要保留
-keepclassmembers -keepclassmembers [,modifier,...] class_spec  指定要保留的类成员,如果它们所属的类被保留的话
-keepclasseswithmembers -keepclasseswithmembers [,modifier,...] class_spec 指定需要保留的类,如果其成员符合条件
-keepnames class_spec 等价于-keep,allowshrinking class_spec 指定其名称需要保留的类和类成员,如果在压缩阶段这些类没有被删除的话。该选项仅用于混淆阶段
-keepclassmembernames -keepclassmembernames class_spec 指定名称要保留的类成员,如果在压缩阶段这些类没有被删除的话。该选项仅用于混淆阶段
-keepclasseswithmembernames -keepclasseswithmembernames class_spec 指定要保留的类和类成员,如果所有指定的类成员在经历了压缩阶段还存在
-printseeds [filename] 打印所有匹配-keep的类和类成员,默认打印到标准输出

-keep选项支持添加限定符,格式为: -keep,限定符 ,限定符包括:

限定符 说明 
includedescriptorclasses 方法、字段的类型描述符中的任何类,跟随被keep的方法/字段一并保留,通常用于保留Native方法的名字时,防止Native方法参数的名字被修改,以保证和Native库兼容
allowshrinking 指定是否入口点可以被压缩
allowoptimization 指定是否入口点可以被优化
allowobfuscation 指定是否入口点可以被混淆
压缩选项
选项  说明 
-dontshrink  不压缩,默认压缩输入文件:除了匹配-keep的、以及它们直接、间接依赖的所有类、类成员,都被移除。压缩阶段可能随着优化阶段运行
-whyareyoukeeping class_spec 打印类、类成员被保留的原因
优化选项
选项 说明
-dontoptimize 不进行优化。默认情况下优化启用,所有方法都在字节码级别进行优化
-optimizations opt_filter 在更细粒度上控制进行哪些优化
-optimizationpasses n 优化的步骤数,默认1步,如果发现没有可优化的,后续步骤自动省略
-assumenosideeffects class_spec 指定不具有副作用(不改变任何状态信息)的方法规格,如果这些方法的返回值没有被使用,那么这样的调用会清除
-allowaccessmodification 是否允许放宽类、类成员的访问限定符。这可能有利于优化,例如对getter()进行内联,需要相应字段成为public的
-mergeinterfacesaggressively 允许接口合并,甚至在实现类没有实现所有接口方法的情况下
混淆选项
选项  说明 
-dontobfuscate 是否进行混淆,默认是。除了匹配-keep系列选项的类、类成员的名字将被随机的改为短名。为了方便调试而保留的内部属性,例如源代码名称、变量名、行号,都将被移除
-printmapping [filename] 打印混淆前后类名、类成员名的对照
-applymapping filename 指定一个先前生成的混淆名对照表,本次依照该对照继续混淆,不在表中的成员生成新的名字
-obfuscationdictionary filename 指定存放有效混淆后变量名的文件
-overloadaggressively 混淆时支持激进的重载,允许多个字段、方法使用重复的名字,只要参数和返回值不同
-useuniqueclassmembernames 让不同名的类成员具有不同的混淆后的名称,让同名的类成员混淆后的名称依旧相同
-dontusemixedcaseclassnames 混淆后,不使用混合大小写的类名
-keeppackagenames [pkg_filter] 指定不混淆的包的过滤器,过滤器支持* **和前导的!
-flattenpackagehierarchy [pkg_name] 对所有被重命名的包进行重新打包,如果不指定参数值,则打包到根目录
-repackageclasses [pkg_name] 对所有被重命名的类进行重新打包,如果不指定参数值,则打包到根目录
-keepattributes [attr_filter] 指定需要保留的所有可选属性,参数值是逗号分隔的,所有JVM或ProGuard支持的属性值。支持使用? * ** !。在处理库的时候,至少应该保留Exceptions, InnerClasses, Signature属性,如果程序依赖于注解,则应该保留
-keepparameternames 保留方法参数的名称和类型。该选项实质上保留了一个修剪(trim)后的LocalVariableTable、LocalVariableTypeTable这两个调试属性,在处理库时可能使用。注意,方法局部变量的名称依旧会混淆
-renamesourcefileattribute [string] 设置SourceFile、SourceDir 属性为指定的常量值
-adaptclassstrings [class_filter] 代表了类名的字符串常量值,是否也被混淆(与目标类的名字保持一致)。如果不指定参数值,所有代表类名的字符串常量都被混淆
-adaptresourcefilenames [file_filter] 是否重命名资源文件,如果其文件名反映了一个被混淆的类的名字
-adaptresourcefilecontents [file_filter] 是否修改资源文件中的类名,如果对应的类的名字已经被混淆。ProGuard使用平台默认字符集读取文件,如果需要改变这一行为,需要设置LANG环境变量或者JVM系统属性file.encoding
预校验选项
选项 说明 
-dontpreverify 指定不进行字节码预校验,对于Java6+默认开启
-microedition 只是目标类文件将在JME平台上运行
一般选项
选项 说明 
-verbose 在处理时打印冗长的信息
-dontnote [class_filter] 不打印配置选项中,与正则式匹配的类相关的错误或者疏忽
-dontwarn [class_filter] 不打印配置选项中,与正则式匹配的类相关的重要错误,例如unresolved references 
-ignorewarnings 忽略所有警告,强制进行处理。这可能很危险
-printconfiguration [filename] 打印解析后的配置信息到目标文件
-dump [filename] 打印处理后的类文件的内部结构
类路径和过滤器

ProGuard支持通过Classpath指定输入文件、输出文件。Classpath的条目使用传统的分隔符(Unix:,Windows;),条目的顺序决定优先级,如果出现重复类,前面的生效。

每个输入条目可以是 :类/资源文件、apk、jar、war、aar、zip、目录;每个输出条目可以是apk、jar、war、aar、zip、目录。各种压缩包类型支持嵌套,每个输入条目输出到最接近它的输出条目中。

ProGuard支持对Classpath条目的内容进行过滤,下面是几个例子:

  1. rt.jar(java/**.class,javax/**.class) 匹配rt.jar中所有java/javax开头的包中的类
  2. input.jar(!**.gif,images/**)匹配input.jar中images/目录中所有文件,除了GIF
  3. input.war(lib/**.jar,support/**.jar;**.class,**.gif)  匹配input.war的lib、support目录下所有jar,以及所有类文件和GIF文件

?匹配文件名中的单个字符;通配符*匹配文件名中的多个字符;**匹配路径中的任意字符(包括多级目录层次);!表示取反。这种过滤器语法适用于配置选项的多个方面,例如文件、目录、类、包、属性、优化,等等。

关于文件名

ProGuard支持通过绝对路径/相对路径指定文件名,相对路径按如下规则顺序解析:

  1. 相对于-basedirectory目录
  2. 相对于配置文件所在目录
  3. 相对于工作目录

文件名可以包含使用 <> 包围的Java系统属性,例如 <java.home>/lib/rt.jar 

如果文件名有空格,必须使用引号包围,例如 -injars "/your dir/your prog.jar" 

类规格(class_spec)

类规格用于指定类、类成员的匹配规则,语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# [] 表示其中的内容是可选的
# ... 表示前面列表中的项的任意组合是支持的
# | 用于分割两个备选项
# class/interface/enum用于引用相应的Java类型
# classname为全限定的类名,内部类使用$界定,例如java.lang.Thread$State。类名支持* ** ?通配符
# extends/implements的作用引用继承或者实现的Java类型
# @用于限定类、类成员被指定的类型所注解,annotationtype的格式和class一致
# <init> <fields> <methods> *分别匹配任意构造器、任意字段、任意方法和任意类成员
# 字段名、方法名支持通配符?、*
 
# argumenttype fieldtype returntype等支持以下通配符:
# %匹配任意基本类型;?匹配类名的单个字符;*匹配类全名中的多个字符,单不能跨越包分隔符 **匹配类全名中任意多个字符
# ***匹配任意类型;...匹配任意类型的任意数量的参数
 
 
[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname
    [extends|implements [@annotationtype] classname]
[{
    [@annotationtype] [[!]public|private|protected|static|volatile|transient ...]
        <fields> | (fieldtype fieldname);
        
    [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...]
        <methods> | <init>(argumenttype,...) | classname(argumenttype,...) | (returntype methodname(argumenttype,...));
        
    [@annotationtype] [[!]public|private|protected|static ... ] *;
    ...
}]
配置示例

压缩、优化并混淆一个简单的Java程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
-injars       myapplication.jar
-outjars      myapplication_out.jar
-libraryjars  <java.home>/lib/rt.jar  #使用系统属性
-printmapping myapplication.map       #打印混淆名称的映射关系
-optimizationpasses 3                 #三步优化
-overloadaggressively
-repackageclasses ''
-allowaccessmodification
 
#以main函数为入口点
-keep public class mypackage.MyMain {
    public static void main(java.lang.String[]);
}

压缩、优化并混淆一个库的典型配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
-injars       in.jar
-outjars      out.jar
-libraryjars  <java.home>/lib/rt.jar
-printmapping out.map
#保留本地变量表(LocalVariableTable)、本地变量类型表(LocalVariableTypeTable)
-keepparameternames
-renamesourcefileattribute SourceFile
#保留异常表,以便编译器知道哪些异常可能被抛出
#保留InnerClasses,否则外部无法引用内部类
#保留Signature,否则无法访问泛型
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
 
#保留所有公共类的公共/保护方法,这是库暴露的接口部分
-keep public class * {
    public protected *;
}
 
#保留native方法的规格,以便能与native库链接
-keepclasseswithmembernames,includedescriptorclasses class * {
    native <methods>;
}
 
-keepclassmembers,allowoptimization enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
#保留必要的类成员,以便串行化机制可用
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

压缩、优化并混淆一个完整的安卓应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#注意,标准的Android SDK构建过程已经集成了ProGuard,仅需要解除project.properties中的proguard.config=...
#因此下面的配置示例并不需要,这里仅仅说明如何从头实现合适的ProGuard配置
 
-injars      bin/classes
-injars      libs
-outjars     bin/classes-processed.jar
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar
 
-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*
 
#这些类型必须被原样的保留,不能移除或者重命名
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
 
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}
 
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}
 
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
 
-keepclassmembers class * extends android.content.Context {
   public void *(android.view.View);
   public void *(android.view.MenuItem);
}
 
-keepclassmembers class * implements android.os.Parcelable {
    static ** CREATOR;
}
 
-keepclassmembers class **.R$* {
    public static <fields>;
}
 
-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

通过指定日志方法没有副作用,可以移除代码中的日志记录调用:

1
2
3
4
5
6
7
-assumenosideeffects interface org.slf4j.Logger {
    public void trace(...);
    public void debug(...);
    public void info(...);
    public void warn(...);
    public void error(...);
}

升级字节码文件为Java6版本,这样可以更高效的载入JVM:

1
2
3
4
5
6
7
8
9
-injars      in.jar
-outjars     out.jar
-libraryjars <java.home>/lib/rt.jar
 
-dontshrink
-dontoptimize
-dontobfuscate
 
-target 1.6

保留所有类、类成员上的所有注解设置:

1
-keepattributes *Annotation*

保留数据库驱动:

1
2
#数据库驱动往往是动态加载的
-keep class * implements java.sql.Driver

使用依赖注入的应用中,防止私有类成员被移除:

1
2
3
4
5
6
7
8
9
-keepclassmembers class * {
    @javax.annotation.Resource *;
}
-keepclassmembers class * {
    @javax.inject.Inject *;
}
-keepclassmembers class * {
    @org.springframework.beans.factory.annotation.Autowired *;
}

当程序被混淆后,适配资源文件名、资源文件内容:

1
2
-adaptresourcefilenames    **.properties,**.gif,**.jpg
-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
与Maven集成

可以通过Maven插件proguard-maven-plugin进行集成,参考:Maven POM文件配置示例

 

 

 

 

 

 

← 基于Apache Cordova开发移动应用程序
PhoneGap学习笔记 →
2 Comments On This Topic
  1. 回复
    Android混淆(ProGuard)从0到1 - 算法网
    2019/05/30

    […] https://blog.gmem.cc/proguard-study-note […]

  2. 回复
    Android分享:代码混淆那些事 – FIXBBS
    2020/10/30

    […] https://blog.gmem.cc/proguard-study-notehttp://developer.android.com/intl/zh-cn/tools/help/proguard.html […]

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • Maven POM文件配置示例
  • Tomcat知识集锦
  • Ubuntu下安装JDK1.7
  • log4j配置文件样本
  • 基于JavaConfig方式的Spring+Hibernate集成

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2