StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题。比如,如果你在UI线程中进行了网络或者磁盘操作,StrictMode就会通过Log(logcat )或者对话框的方式把信息提示给你,因为让你的UI线程处理这里操作会被认为是不规范的做法,可能会让你的应用变得比较卡顿。

官网文档:http://developer.android.com/reference/android/os/StrictMode.html

如何启用 StrictMode

我们通常在 Activity 或者自定义的Application类中启动 StrictMode,代码如下:

 public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate();
}

注意:我们只需要在app的开发版本下使用 StrictMode,线上版本避免使用 StrictMode,随意需要通过 诸如 DEVELOPER_MODE 这样的配置变量来进行控制。

下面我们举几个例子来说明 StrictMode 是如何发挥作用的。

代码1:

public class ActivitySimple extends Activity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); StrictMode.setThreadPolicy(new ThreadPolicy.Builder()
.detectAll()
.penaltyDialog() //弹出违规提示对话框
.penaltyLog() //在Logcat 中打印违规异常信息
.build()); this.testNetwork();
} private void testNetwork() {
try {
URL url = new URL("http://www.baidu.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String lines = null;
StringBuffer sb = new StringBuffer();
while ((lines = reader.readLine()) != null) {
sb.append(lines);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

在这里例子中,我们在主线程(UI线程)中执行了网络请求,ThreadPolicy 策略中的 detectAll()方法
包含而来对这类违规操作的检查,同时我们通过penaltyDialog() 和 penaltyLog() 两个方法将违规信息提示给开发者。

在运行这段代码是,我们会看到下图中的对话框提示:

在LogCat 中我们会看到这样的日志信息:

... D/StrictMode(26365): StrictMode policy violation; ~duration=58 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=63 violation=4
... D/StrictMode(26365): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1134)
... D/StrictMode(26365): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163)
... D/StrictMode(26365): at libcore.io.IoBridge.recvfrom(IoBridge.java:557)
... D/StrictMode(26365): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:490)
... D/StrictMode(26365): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
...
(后面的部分省略)

StrictMode 详解

StrictMode 通过策略方式来让你自定义需要检查哪方面的问题。 主要有两中策略,一个时线程方策略(ThreadPolicy),一个是VM方面的策略(VmPolicy)。

  • ThreadPolicy 主要用于发现在UI线程中是否有读写磁盘的操作,是否有网络操作,以及检查UI线程中调用的自定义代码是否执行得比较慢。

  • VmPolicy,主要用于发现内存问题,比如 Activity内存泄露, SQL 对象内存泄露, 资源未释放,能够限定某个类的最大对象数。

ThreadPolicy 详解

StrictMode.ThreadPolicy.Builder 主要方法如下:

  • detectNetwork() 用于检查UI线程中是否有网络请求操作,上面的代码的就是网络请求违规的问题。

  • detectDiskReads() 和 detectDiskReads() 是磁盘读写检查,触发时会打印出如下日志(以 detectDiskReads() 为例):

    ... D/StrictMode(27429): StrictMode policy violation; ~duration=33 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=31 violation=2
    ... D/StrictMode(27429): at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1118)
    ... D/StrictMode(27429): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:106)
    ... D/StrictMode(27429): at java.io.File.createNewFile(File.java:941)
    ... D/StrictMode(27429): at com.ap.teststrictmode.ActivityTestDisk.testWriteDisk(ActivityTestDisk.java:51)
    ... D/StrictMode(27429): at com.ap.teststrictmode.ActivityTestDisk.onCreate(ActivityTestDisk.java:40)
    ... D/StrictMode(27429): at android.app.Activity.performCreate(Activity.java:5122)
    ... D/StrictMode(27429): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
    ... D/StrictMode(27429): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
    ...
    (后面的部分省略)
  • detectCustomSlowCalls() 主要用于帮助开发者发现UI线程调用的那些方法执行得比较慢,要和 StrictMode.noteSlowCall 配合使用,StrictMode.noteSlowCall 只有通过 StrictMode.noteSlowCall用来标记“可能会”执行比较慢的方法,只有标记过的方法才能被检测到,日志中会记录方法的执行时间(比如
    ~duration=2019 ms)。看下面的例子: 

    代码2:

    public class ActivityTestDetectCustomSlowCalls extends Activity {
    
    private TextView textView = null;
    
    private static boolean isStrictMode = false;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activitymain);
    this.textView = (TextView) findViewById(R.id.textview);
    this.textView.setText("In ActivityTestDetectCustomSlowCalls");
    if(! isStrictMode){
    StrictMode.setThreadPolicy(new ThreadPolicy.Builder()
    .detectCustomSlowCalls()
    .penaltyLog()
    .build());
    isStrictMode = true;
    }
    this.slowCall1();
    this.slowCall2();
    } /*
    * 没有标记的方法
    */
    private void slowCall_1(){
    //用来标记潜在执行比较慢的方法
    SystemClock.sleep(1000 2);
    } /
    * 标记过的方法
    /
    private void slowCall_2(){
    //用来标记潜在执行比较慢的方法
    StrictMode.noteSlowCall("slowCall 2");
    SystemClock.sleep(1000 2);
    }
    }

    在logcat 中我们只能看到和方法 slowCall_2()(因为通过StrictMode.noteSlowCall()标记过)相关的日志:

    ...: D/StrictMode(1349): StrictMode policy violation; **~duration=2019 ms: android.os.StrictMode$StrictModeCustomViolation: policy=24 violation=8 msg=slowCall 2
    ...: D/StrictMode(1349): at android.os.StrictMode$AndroidBlockGuardPolicy.onCustomSlowCall(StrictMode.java:1105)
    ...: D/StrictMode(1349): at android.os.StrictMode.noteSlowCall(StrictMode.java:1903)
    ...: D/StrictMode(1349): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls.slowCall_2(ActivityTestDetectCustomSlowCalls.java:52)
    ...: D/StrictMode(1349): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls.onCreate(ActivityTestDetectCustomSlowCalls.java:35)
    ...: D/StrictMode(1349): at android.app.Activity.performCreate(Activity.java:5122)
    ...: D/StrictMode(1349): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
    ...: D/StrictMode(1349): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
    ...: D/StrictMode(1349): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358)
    ...: D/StrictMode(1349): at android.app.ActivityThread.access$600(ActivityThread.java:156)
    ...: D/StrictMode(1349): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1340)
    ...: D/StrictMode(1349): at android.os.Handler.dispatchMessage(Handler.java:99)
    ...: D/StrictMode(1349): at android.os.Looper.loop(Looper.java:153)
    ...
    (后面的部分省略)

    当然你也可以在其他线程中使用 detectCustomSlowCalls(),但是没有什么实际意义,也看不到方法执行时间,比如:

public class ActivityTestDetectCustomSlowCalls extends Activity {

    private TextView textView = null;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); this.textView = (TextView) findViewById(R.id.text_view); this.textView.setText("In ActivityTestDetectCustomSlowCalls"); new Thread(){
public void run() {
StrictMode.setThreadPolicy(new ThreadPolicy.Builder()
.detectCustomSlowCalls()
.penaltyLog()
.build()); this.slowCallInCustomThread();
}; private void slowCallInCustomThread(){
//用来标记潜在执行比较慢的方法
StrictMode.noteSlowCall("slowCallInCustomThread");
SystemClock.sleep(1000 * 2);
}
}.start();;
}
}

日志输出如下:

...: D/StrictMode(2418): StrictMode policy violation: android.os.StrictMode$StrictModeCustomViolation: policy=24 violation=8 msg=slowCallInCustomThread
...: D/StrictMode(2418): at android.os.StrictMode$AndroidBlockGuardPolicy.onCustomSlowCall(StrictMode.java:1105)
...: D/StrictMode(2418): at android.os.StrictMode.noteSlowCall(StrictMode.java:1903)
...: D/StrictMode(2418): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls$1.slowCallInCustomThread(ActivityTestDetectCustomSlowCalls.java:35)
...: D/StrictMode(2418): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls$1.run(ActivityTestDetectCustomSlowCalls.java:30)
...
(后面的部分省略)
  • penaltyDeath(),当触发违规条件时,直接Crash掉当前应用程序。

  • penaltyDeathOnNetwork(),当触发网络违规时,Crash掉当前应用程序。

  • penaltyDialog(),触发违规时,显示对违规信息对话框。

  • penaltyFlashScreen(),会造成屏幕闪烁,不过一般的设备可能没有这个功能。

  • penaltyDropBox(),将违规信息记录到 dropbox 系统日志目录中(/data/system/dropbox),你可以通过如下命令进行插件:

    adb shell dumpsys dropbox dataappstrictmode  --print
    

    会得到如下的信息:

    2014-05-04 14:56:32 dataappstrictmode (text, 2627 bytes)
    Process: com.ap.teststrictmode
    Flags: 0x40a8be46
    Package: com.ap.teststrictmode v1 (1.0)
    Build: Xiaomi/pisces/pisces:4.2.1/JOP40D/JXCCNBA13.0:user/release-keys
    System-App: false
    Uptime-Millis: 66679049
    Loop-Violation-Number: 10
    Duration-Millis: 24
    android.os.StrictMode$StrictModeNetworkViolation: policy=191 violation=4
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1136)
    at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163)
    at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
    at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
    at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
    at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
    at java.io.InputStream.read(InputStream.java:163)
    at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:142)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:227)
    at libcore.io.Streams.readAsciiLine(Streams.java:201)
    at libcore.net.http.ChunkedInputStream.readChunkSize(ChunkedInputStream.java:77)
    at libcore.net.http.ChunkedInputStream.read(ChunkedInputStream.java:68)
    at java.io.InputStream.read(InputStream.java:163)
    at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:200)
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:154)
    at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:167)
    ...
  • permitCustomSlowCalls()、permitDiskReads ()、permitDiskWrites()、permitNetwork: 如果你想关闭某一项检测,可以使用对应的permit*方法。

VMPolicy 详解

  • detectActivityLeaks() 用户检查 Activity 的内存泄露情况,比如下面的代码:
public class ActivityTestActivityLeaks extends Activity {

    private static boolean isStrictMode = false;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if(! isStrictMode){ StrictMode.setVmPolicy(new VmPolicy.Builder()
.detectActivityLeaks()
.penaltyLog()
.build());
isStrictMode = true;
} new Thread() {
@Override
public void run() {
while (true) { SystemClock.sleep(1000);
}
}
}.start();
}
}

我们反复旋转屏幕就会输出如下信息(重点在 instances=4; limit=1 这一行):

...: E/StrictMode(4784): class com.ap.teststrictmode.ActivityTestActivityLeaks; instances=4; limit=1
...: E/StrictMode(4784): android.os.StrictMode$InstanceCountViolation: class com.ap.teststrictmode.ActivityTestActivityLeaks; instances=4; limit=1
...: E/StrictMode(4784): at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

这时因为,我们在Activity中创建了一个Thread匿名内部类,而匿名内部类隐式持有外部类的引用。而每次旋转屏幕是,Android会新创建一个Activity,而原来的Activity实例又被我们启动的匿名内部类线程持有,所以不会释放,从日志上看,当先系统中该Activty有4个实例,而限制是只能创建1各实例。我们不断翻转屏幕,instances 的个数还会持续增加。

  • detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),资源没有正确关闭时回触发,比如下面的代码:

public class MainActivityTestDetectLeakedClosableObjects extends Activity { private static boolean isStrictMode = false; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if(! isStrictMode){
StrictMode.setVmPolicy(new VmPolicy.Builder()
.detectLeakedClosableObjects()
.penaltyLog()
.build());
isStrictMode = true;
} File newxmlfile = new File(Environment.getExternalStorageDirectory(), "aaa.txt");
try {
newxmlfile.createNewFile();
FileWriter fw = new FileWriter(newxmlfile);
fw.write("aaaaaaaaaaa");
//fw.close(); 我们在这里故意没有关闭 fw
} catch (IOException e) {
e.printStackTrace();
} }
}

会产生如下异常信息:

... E/StrictMode(22056): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
... E/StrictMode(22056): java.lang.Throwable: Explicit termination method 'close' not called
... E/StrictMode(22056): at dalvik.system.CloseGuard.open(CloseGuard.java:184)
... E/StrictMode(22056): at java.io.FileOutputStream.(FileOutputStream.java:90)
... E/StrictMode(22056): at java.io.FileOutputStream.(FileOutputStream.java:73)
... E/StrictMode(22056): at java.io.FileWriter.(FileWriter.java:42)
... E/StrictMode(22056): at com.ap.teststrictmode.MainActivityTestDetectLeakedClosableObjects.onCreate(MainActivityTestDetectLeakedClosableObjects.java:44)
... E/StrictMode(22056): at android.app.Activity.performCreate(Activity.java:5122)
... E/StrictMode(22056): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
... E/StrictMode(22056): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
... E/StrictMode(22056): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358)
... E/StrictMode(22056): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3865)
(后面的省略)

detectLeakedSqlLiteObjects() 和 detectLeakedClosableObjects()的用法类似,只不过是用来检查 SQLiteCursor 或者 其他 SQLite 对象是否被正确关闭。

  • detectLeakedRegistrationObjects() 用来检查 BroadcastReceiver 或者 ServiceConnection 注册类对象是否被正确释放,看下面的代码
public class ActivityTestLeakedRegistrationObjects extends Activity {
private TextView textView = null;
private static boolean isStrictMode = false;
private MyReceiver receiver = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); this.textView = (TextView) findViewById(R.id.text_view); this.textView.setText("In ActivityTestLeakedRegistrationObjects"); if(! isStrictMode){
StrictMode.setVmPolicy(new VmPolicy.Builder()
.detectLeakedRegistrationObjects()
.penaltyLog()
.build());
isStrictMode = true;
} this.receiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.MY_BROADCAST");
registerReceiver(this.receiver, filter);
} @Override
protected void onDestroy() {
super.onDestroy();
}
}

输入信息如下:

...: E/ActivityThread(24442): Activity com.ap.teststrictmode.ActivityTestLeakedRegistrationObjects has leaked IntentReceiver com.ap.teststrictmode.MyReceiver@41f1f128 that was originally registered here. Are you missing a call to unregisterReceiver()?
...: E/ActivityThread(24442): android.app.IntentReceiverLeaked: Activity com.ap.teststrictmode.ActivityTestLeakedRegistrationObjects has leaked IntentReceiver com.ap.teststrictmode.MyReceiver@41f1f128 that was originally registered here. Are you missing a call to unregisterReceiver()?
...: E/ActivityThread(24442): at android.app.LoadedApk$ReceiverDispatcher.(LoadedApk.java:825)
...: E/ActivityThread(24442): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:596)
...: E/ActivityThread(24442): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1388)
...: E/ActivityThread(24442): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1368)
...

正确做法应该是在 onDestroy() 方法中将 receiver 释放掉:

 @Override
protected void onDestroy() {
unregisterReceiver(this.receiver);
super.onDestroy();
}
  • setClassInstanceLimit(),设置某个类的同时处于内存中的实例上限,可以协助检查内存泄露。比如下面的代码:
public class ActivityTestObjectLimit extends Activity {
private static class MyClass{} private static boolean isStrictMode = false; private static List<MyClass> classList = new ArrayList<ActivityTestObjectLimit.MyClass>(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if(! isStrictMode){
StrictMode.setVmPolicy(new VmPolicy.Builder()
.setClassInstanceLimit(MyClass.class, 2)
.penaltyLog()
.build());
isStrictMode = true;
} classList.add(new MyClass());
classList.add(new MyClass());
classList.add(new MyClass());
classList.add(new MyClass());
classList.add(new MyClass());
classList.add(new MyClass());
classList.add(new MyClass());
classList.add(new MyClass());
}
}

日志信息如下:

...: E/StrictMode(27681): class com.ap.teststrictmode.ActivityTestObjectLimit$MyClass; instances=72; limit=2
...: E/StrictMode(27681): android.os.StrictMode$InstanceCountViolation: class com.ap.teststrictmode.ActivityTestObjectLimit$MyClass; instances=8; limit=2
...: E/StrictMode(27681): at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

注意:上面的异常一般都在GC之后抛出,如果测试的时候没有现象,可以多翻转几次屏幕,或者通过DDMS工具手动触发一下。

StrictMode 详解的更多相关文章

  1. StrictMode使用详解

    http://hb.qq.com/a/20110914/000054.htm http://www.android100.org/html/201204/25/1097.html http://www ...

  2. Android严苛模式StrictMode使用详解

    StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题,以达到提升应用响应能力的目的.举个例子来说,如果开发者在UI线程中进行了 ...

  3. Android application 和 activity 标签详解

    extends:http://blog.csdn.net/self_study/article/details/54020909 Application 标签 android:allowTaskRep ...

  4. Context知识详解

    Context知识详解 建议配合context知识架构图食用. 一.什么是Context 贴一个官方解释: Interface to global information about an appli ...

  5. Android之Activity启动流程详解(基于api28)

    前言 Activity作为Android四大组件之一,他的启动绝对没有那么简单.这里涉及到了系统服务进程,启动过程细节很多,这里我只展示主体流程.activity的启动流程随着版本的更替,代码细节一直 ...

  6. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  7. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  8. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  9. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

随机推荐

  1. centos安装rocketMQ

    1.下载安装包 http://rocketmq.apache.org/release_notes/ 这里选择 4.4.0 版本,点击进去 可以选择源码包或者二进制文件,这里选择二进制文件(ps:如果选 ...

  2. FLV 数据封装格式

    https://www.cnblogs.com/chyingp/p/flv-getting-started.html https://blog.csdn.net/ai2000ai/article/de ...

  3. nginx代理(正向代理和反向代理)

    正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容 ...

  4. 在Eclipse配置Tomcat服务器+JSP实例创建

    欢迎任何形式的转载,但请务必注明出处. 1.jdk安装及环境配置 点击进入教程 2.Eclipse安装 点击进入官网下载 注意下载完成打开.exe后,出现的界面,有很多版本供选择.选择下图版本 3.T ...

  5. How to change SAPABAP1 schema password In HANA

    Symptom How to change SAPABAP1 schema password Environment HANA 1.x HANA 2.x Resolution Shutdown the ...

  6. BKP和RTC

    Stm32内部有多个BKP寄存器,在主电源被切断或者系统产生复位的时候,BKP寄存器仍然可以利用备用电源的支持保持其重要内容. BKP在实际应用中可以存入重要数据,防止被恶意查看. BKP有入侵检测, ...

  7. 前端框架开始学习Vue(一)

    MVVM开发思想图(图片可能会被缩小,请右键另存查看,图片来源于网络)   定义基本Vue代码结构   1 v-text,v-cloak,v-html命令 默认 v-text没有闪烁问题,但是会覆盖元 ...

  8. Python 渗透测试编程技术方法与实践 ------全书整理

    1.整个渗透测试的工作阶段 ( 1 )前期与客户的交流阶段.( 2 )情报的收集阶段.( 3 )威胁建模阶段.( 4 )漏洞分析阶段.( 5 )漏洞利用阶段.( 6 )后渗透攻击阶段.( 7 )报告阶 ...

  9. Window Server 2008 概述

    Windows历史版本 Windows工作站发展历史 Windows95——>Windows98——>Windows2000——>WindowsXP——>Vista——> ...

  10. CentOS7下编译安装Python3.7.x【亲测有效】

    所有操作都在root用户下操作 下载安装包 编译安装 建立软链接 验证 安装: 更新yum: yum update 安装Python依赖: yum install openssl-devel bzip ...