性能优化

Android 性能优化 (一)APK高效瘦身

http://blog.csdn.net/whb20081815/article/details/70140063

Android 性能优化 (二)数据库优化 秒变大神
http://blog.csdn.net/whb20081815/article/details/70142033

Android 性能优化(三)布局优化 秒变大神

http://blog.csdn.net/whb20081815/article/details/70147958

 Android 性能优化(四)内存优化OOM 秒变大神
http://blog.csdn.net/whb20081815/article/details/70243105
Android 性能优化(五)ANR 秒变大神
http://blog.csdn.net/whb20081815/article/details/70245594
Android 性能优化(六) RelativeLayout和LinearLayout性能比较
http://blog.csdn.net/whb20081815/article/details/74465870

Android 性能优化<七>自定义view绘制优化

http://blog.csdn.net/whb20081815/article/details/74474736
原理和源码分析:
1.Android Binder 作为 IPC 机制原理和面试回答   
http://blog.csdn.net/whb20081815/article/details/74436204
2.

Android AIDL进程IPC通信 一次就好

http://blog.csdn.net/whb20081815/article/details/70766913

3.

Android AIDL进程IPC通信 一次就好

http://blog.csdn.net/whb20081815/article/details/70766913

4.

Android反射(Reflect)完全解析--强势来袭

http://blog.csdn.net/whb20081815/article/details/61198050

5.

Android 2分钟学会xUtils 注解 Annotation(实例+原理)

http://blog.csdn.net/whb20081815/article/details/62423840
6. Android 上下文Context(最权威的官方教程)
http://blog.csdn.net/whb20081815/article/details/70258715
7.Android Activty的加载过程 启动流程 源码分析
http://blog.csdn.net/whb20081815/article/details/76596473
线程:
1).Android 价值千万   java线程专题:Wait&notify&join&Yield
http://blog.csdn.net/whb20081815/article/details/65627387
2).Android 价值千万    java多线程同步 <二>Callable和Future&FutureTask
http://blog.csdn.net/whb20081815/article/details/65630694
3).Android 价值千万    java多线程<三>生产者消费者模型四种实现方法
http://blog.csdn.net/whb20081815/article/details/65635647
 4).

Android 价值千万    java多线程同步 <四> synchronized&Lock&Atomic6种方式

http://blog.csdn.net/whb20081815/article/details/66971983

5).Android 价值千万java多线程同步 <五>CountDownLatch(计数器)和Semaphore(信号量)

http://blog.csdn.net/whb20081815/article/details/68498371
UI,view和动画框架
1).Android 深入理解 View 的绘制流程和机制
http://blog.csdn.net/whb20081815/article/details/62236641
2).

Android快速理解Activity、View及Window&WindowManager之间关系

http://blog.csdn.net/whb20081815/article/details/62419059
3).Android 动画用法+原理(Property Animation) 酷炫 UI动画
http://blog.csdn.net/whb20081815/article/details/64501074

4).Android 性能优化<七>自定义view绘制优化

http://blog.csdn.net/whb20081815/article/details/74474736
wapper :包装
 
分类
1.性能优化
2.原理和源码分析------插件化框架的一部分
3.线程模型分析
4.UI,view和动画框架
5.JAVA 面向对象进阶
问题一
1.context启动Activity=======搞定!
2.一个程序里面的每一个模块都可以运行起来。

 

组件化开发就是将一个app分成多个模块,每个模块都是一个组件(Module),开发的过程中我们可以让这些组件相互依赖或者单独调试部分组件等,但是最终发布的时候是将这些组件合并统一成一个apk,这就是组件化开发。
插件化开发和组件化开发略有不用,插件化开发时将整个app拆分成很多模块,这些模块包括一个宿主和多个插件,每个模块都是一个apk(组件化的每个模块是个lib),最终打包的时候将宿主apk和插件apk分开或者联合打包。

做插件化真正的目的:是为了去适应并行开发,是为了解耦各个模块,是为了避免模块之间的交叉依赖,是为了加快编译速度,从而提高并行开发效率。

 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

加入一个app工程只有一个组件,随着app业务的壮大模块越来越多,代码量超10万是很正常的,这个时候我们会遇到以下问题

  • 稍微改动一个模块的一点代码都要编译整个工程,耗时耗力
  • 公共资源、业务、模块混在一起耦合度太高
  • 不方便测试
  • 项目新功能的添加,无法确定与用户匹配性,发生严重异常往往牵一发而动全身,只能紧急发布补丁版本,强制用户进行更新.结果频繁的更新

可以干什么:

  • 热修复,热修复其实也是动态加载原理

  • 换肤,使用动态的资源加载可以实现换肤功能

    实现免安装的功能

  • 还可以通过hook系统的一些类做一些你想做的坏事。

    • 插件化最早出现是因为65535问题出现的,用于查分多个dex并动态加载dex来防止65535问题

    • 现在很多公司用插件化来做模块的动态加载,这样既能实现web端一样的随时更新,还能减少apk包的体积,其实就是加载一个未安装的apk。

Android插件化开发框架

1.360插件化框架=======RePlugin有什么用
 RePlugin解决的是各个功能模块能独立升级,又能需要和宿主、插件之间有一定交互和耦合
在阅读他们开源的东西的时候,确实是我读过开源项目里面算是友好的, 至少注释是这样子的. 尤其是有阿里atlas 这种反面例子做对比
强大的介绍
http://news.163.com/17/0701/21/CO9PEL3400014AEE.html
官方下载地址:
https://github.com/Qihoo360/RePlugin/wiki
2.滴滴出行插件化框架
3.携程插件化框架----DynamicAPK      之后曾和玉刚聊天,他十分感慨当年如何举步维艰地开发这个框架。我当时在途牛工作,使用了这个Android插件化框架。
任玉刚的:dynamic-load-apk,这个项目使用的是一种代理的方式去实现 
4.Atlas  阿里的
5.ACDD插件化框架
6.DroidPlugin360的老式方案-----------------DroidPlugin,这个项目是通过hook系统类来实现 
7.Android-Plugin-Framework

8.DL APK动态加载框架

(女娲)

四个月前(2015年8月初) , BunnyBlue开源了一个名为OpenAtlas的插件化框架, 这个插件化的来源可能并非所有人知晓, 我在这里概括一下:

2013年, 朱碧军同学在阿里的一次技术沙龙中分享了一个插件化框架: Atlas ,这个框架用在淘宝的Android客户端,没有开源,沙龙中也没有对该插件化的具体实现做讲解.(阿里技术沙龙)

15年, BunnyBlue同学在研究淘宝客户端时发现,Atlas框架没有混淆的十分彻底(在com.android.atlas下),于是花了一些时间对其中代码的实现进行了逆向,并在8月初开源了这一成果,并取名为OpenAtlas.

后来,由于涉及到一些代码来源方面的问题, OpenAtlas项目关闭,后改名为:ACCD(bunnyblue/ACDD · GitHub).

需要解决的问题:(代码加载和资源加载)
  • 编译期:资源和代码的编译
  • 运行时:资源和代码的加载
  • 还有一个问题就是对四大组件的生命周期管理
Android的资源编译依赖一个强大的命令行工具:aapt,它位于<SDK>/build-tools/<buildToolsVersion>/aapt

插件化原理解读:
类的加载可以使用Java的ClassLoader机制,但是对于Android来说,并不是说类加载进来就可以用了,很多组件都是有“生命”的
;因此对于这些有血有肉的类,必须给它们注入活力,也就是所谓的组件生命周期管理;
另外,如何管理加载进来的类也是一个问题。假设多个插件依赖了相同的类,是抽取公共依赖进行管理还是插件单独依赖?这就是ClassLoader的管理问题;

资源加载

资源加载方案大家使用的原理都差不多,都是用AssetManager的隐藏方法addAssetPath;但是,不同插件的资源如何管理?是公用一套资源还是插件独立资源?共用资源如何避免资源冲突?对于资源加载,有的方案共用一套资源并采用资源分段机制解决冲突(要么修改aapt要么添加编译插件);有的方案选择独立资源,不同插件管理自己的资源。

目前国内开源的较成熟的插件方案有DL和DroidPlugin;但是DL方案仅仅对Frameworl的表层做了处理,严重依赖that语法,编写插件代码和主程序代码需单独区分;而DroidPlugin通过Hook增强了Framework层的很多系统服务,开发插件就跟开发独立app差不多;就拿Activity生命周期的管理来说,DL的代理方式就像是牵线木偶,插件只不过是操纵傀儡而已;而DroidPlugin则是借尸还魂,插件是有血有肉的系统管理的真正组件;DroidPlugin Hook了系统几乎所有的Sevice,欺骗了大部分的系统API;掌握这个Hook过程需要掌握很多系统原理,因此学习DroidPlugin对于整个Android FrameWork层大有裨益。

接下来的一系列文章将以DroidPlugin为例讲解插件框架的原理,揭开插件化的神秘面纱;同时还能帮助深入理解Android Framewrok;主要内容如下:

需要学习的一些类:

1.ActivityThread

2.Instrumentation

3.ActivityManager

4.ActivityManagerServiche

5.PackageManagerServic

6.ServiceManager

7.ActivityManagerNative

8.ApplicationThread

如果你不清楚ActivityManagerActivityManagerService以及ActivityManagerNative之间的关系;建议先仔细阅读我之前关于Binder的文章 Binder学习指南。

流程

1.Activity的启动流程

2.service的启动加载

CLassLoader机制,JAVA虚拟机的原理!

罗迪
http://www.infoq.com/cn/articles/android-plug-ins-from-entry-to-give-up
主要利用 Java ClassLoader 的原理,
对于 Android 来说是 DexClassLoader,如下
无非是代理Activity加动态加载类和用AssetManager加载资源
第五点更重要,做Android插件化需要控制两个地方。首先是插件Dex的加载,如何把插件Dex中的类加载到内存?另外是资源加载的问题。
插件可能是apk也可能是so格式,不管哪一种,都不会生成R.id,从而没办法使用。这个问题有好几种解决方案。
一种是是重写Context的getAsset、getResource之类的方法,偷换概念,让插件读取插件里的资源,但缺点就是宿主和插件的资源id会冲突,需要重写AAPT
来源: http://www.infoq.com/cn/articles/android-plug-ins-from-entry-to-give-up
全部的原理过程:
http://blog.csdn.net/yulong0809/article/details/59113935
http://blog.csdn.net/amurocrash/article/details/46965419
准备知识:
1.APK的安装流程      数组     attach
2.Activity的启动流程
1.binder机制
2.动态代理,AIDL里面用的就是binder机制!
Hook机制之动态代理
public static void attachContext() throws Exception{// 先获取到当前的ActivityThread对象
    Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
    Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
    currentActivityThreadMethod.setAccessible(true);
    //currentActivityThread是一个static函数所以可以直接invoke,不需要带实例参数
    Object currentActivityThread = currentActivityThreadMethod.invoke(null);

    // 拿到原始的 mInstrumentation字段
    Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");
    mInstrumentationField.setAccessible(true);
    Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);

    // 创建代理对象
    Instrumentation evilInstrumentation = new EvilInstrumentation(mInstrumentation);

    // 偷梁换柱
    mInstrumentationField.set(currentActivityThread, evilInstrumentation);
}
我们需要修改它的mInstrumentation这个字段为我们的代理对象,我们先实现这个代理对象,
由于JDK动态代理只支持接口,而这个Instrumentation是一个类,没办法,我们只有手动写静态代理类,覆盖掉原始的方法即可
Ok,有了代理对象,我们要做的就是偷梁换柱!代码比较简单,采用反射直接修改:
public class EvilInstrumentation extends Instrumentation {private static final String TAG = "EvilInstrumentation";

    // ActivityThread中原始的对象, 保存起来
    Instrumentation mBase;

    public EvilInstrumentation(Instrumentation base) {mBase = base;
    }public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {// Hook之前, XXX到此一游!
        Log.d(TAG, "\n执行了startActivity, 参数如下: \n" + "who = [" + who + "], " +"\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +"\ntarget = [" + target + "], \nintent = [" + intent +"], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]");

        // 开始调用原始的方法, 调不调用随你,但是不调用的话, 所有的startActivity都失效了.
        // 由于这个方法是隐藏的,因此需要使用反射调用;首先找到这个方法
        try {Method execStartActivity = Instrumentation.class.getDeclaredMethod("execStartActivity",
                    Context.class, IBinder.class, IBinder.class, Activity.class,
                    Intent.class, int.class, Bundle.class);
            execStartActivity.setAccessible(true);
            return (ActivityResult) execStartActivity.invoke(mBase, who,
                    contextThread, token, target, intent, requestCode, options);
        } catch (Exception e) {// 某该死的rom修改了  需要手动适配
            throw new RuntimeException("do not support!!! pls adapt it");
        }}
总结:用代理对象替换原始对象,通过反射的方式得到方法,
(静态代理还是动态代理)替代以前的Instrumentation对象,在执行方法之前做了一些操作,
动态代理?
// 招代理
women = (Shopping) Proxy.newProxyInstance(Shopping.class.getClassLoader(),
        women.getClass().getInterfaces(), new ShoppingHandler(women));

执行启动程序的时候先调用了打印(仅仅为了演示),如下

Log.d(TAG, "\n执行了startActivity, 参数如下: \n" + "who = [" + who + "], " +"\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +"\ntarget = [" + target + "], \nintent = [" + intent +"], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]");

系统服务的获取过程

ActivityManager activityManager=(ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
@Override
public Object getSystemService(String name) {return SystemServiceRegistry.getSystemService(this, name);
}
public static Object getSystemService(ContextImpl ctx, String name) {ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}
tatic {registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
            new CachedServiceFetcher<AccessibilityManager>() {@Override
        public AccessibilityManager createService(ContextImpl ctx) {return AccessibilityManager.getInstance(ctx);
        }});

    registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
            new CachedServiceFetcher<CaptioningManager>() {@Override
        public CaptioningManager createService(ContextImpl ctx) {return new CaptioningManager(ctx);
        }});
registerService(Context.POWER_SERVICE, PowerManager.class,
        new CachedServiceFetcher<PowerManager>() {@Override
    public PowerManager createService(ContextImpl ctx) {IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
        IPowerManager service = IPowerManager.Stub.asInterface(b);
        if (service == null) {Log.wtf(TAG, "Failed to get power manager service.");
        }return new PowerManager(ctx.getOuterContext(),
                service, ctx.mMainThread.getHandler());
    }});
    因此,通过分析我们得知,系统Service的使用其实就分为两步:
IBinder b = ServiceManager.getService("service_name"); // 获取原始的IBinder对象
IXXInterface in = IXXInterface.Stub.asInterface(b); // 转换为Service接口

public class BinderHookHelper {public static void hookClipboardService() throws Exception {final String CLIPBOARD_SERVICE = "clipboard";

        // 下面这一段的意思实际就是: ServiceManager.getService("clipboard");
        // 只不过 ServiceManager这个类是@hide的
        Class<?> serviceManager = Class.forName("android.os.ServiceManager");
        Method getService = serviceManager.getDeclaredMethod("getService", String.class);

        // ServiceManager里面管理的原始的Clipboard Binder对象
        // 一般来说这是一个Binder代理对象
        IBinder rawBinder = (IBinder) getService.invoke(null, CLIPBOARD_SERVICE);

        // Hook 掉这个Binder代理对象的 queryLocalInterface 方法
        // 然后在 queryLocalInterface 返回一个IInterface对象, hook掉我们感兴趣的方法即可.
        IBinder hookedBinder = (IBinder) Proxy.newProxyInstance(serviceManager.getClassLoader(),
                new Class<?>[] { IBinder.class },
                new BinderProxyHookHandler(rawBinder));

        // 把这个hook过的Binder代理对象放进ServiceManager的cache里面
        // 以后查询的时候 会优先查询缓存里面的Binder, 这样就会使用被我们修改过的Binder了
        Field cacheField = serviceManager.getDeclaredField("sCache");
        cacheField.setAccessible(true);
        Map<String, IBinder> cache = (Map) cacheField.get(null);
        cache.put(CLIPBOARD_SERVICE, hookedBinder);
    }
public class BinderProxyHookHandler implements InvocationHandler {private static final String TAG = "BinderProxyHookHandler";

    // 绝大部分情况下,这是一个BinderProxy对象
    // 只有当Service和我们在同一个进程的时候才是Binder本地对象
    // 这个基本不可能
    IBinder base;

    Class<?> stub;

    Class<?> iinterface;

    public BinderProxyHookHandler(IBinder base) {this.base = base;
        try {this.stub = Class.forName("android.content.IClipboard$Stub");
            this.iinterface = Class.forName("android.content.IClipboard");
        } catch (ClassNotFoundException e) {e.printStackTrace();
        }}@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("queryLocalInterface".equals(method.getName())) {Log.d(TAG, "hook queryLocalInterface");

            // 这里直接返回真正被Hook掉的Service接口
            // 这里的 queryLocalInterface 就不是原本的意思了
            // 我们肯定不会真的返回一个本地接口, 因为我们接管了 asInterface方法的作用
            // 因此必须是一个完整的 asInterface 过的 IInterface对象, 既要处理本地对象,也要处理代理对象
            // 这只是一个Hook点而已, 它原始的含义已经被我们重定义了; 因为我们会永远确保这个方法不返回null
            // 让 IClipboard.Stub.asInterface 永远走到if语句的else分支里面
            return Proxy.newProxyInstance(proxy.getClass().getClassLoader(),
public class BinderHookHandler implements InvocationHandler {private static final String TAG = "BinderHookHandler";

    // 原始的Service对象 (IInterface)
    Object base;

    public BinderHookHandler(IBinder base, Class<?> stubClass) {try {Method asInterfaceMethod = stubClass.getDeclaredMethod("asInterface", IBinder.class);
            // IClipboard.Stub.asInterface(base);
            this.base = asInterfaceMethod.invoke(null, base);
        } catch (Exception e) {throw new RuntimeException("hooked failed!");
        }}@TargetApi(Build.VERSION_CODES.HONEYCOMB)@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 把剪切版的内容替换为 "you are hooked"
        if ("getPrimaryClip".equals(method.getName())) {Log.d(TAG, "hook getPrimaryClip");
            return ClipData.newPlainText(null, "you are hooked");
        }// 欺骗系统,使之认为剪切版上一直有内容
        if ("hasPrimaryClip".equals(method.getName())) {return true;
        }return method.invoke(base, args);
特点:实现了多级代理!
1.要修改粘贴板的方法,需要得到manager对象
manager对象通过 ActivityManager activityManager=(ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
得到,manager又是通过ServiceManager来操作的。
目的:把ServiceManager操作的Manager替换成我们的代理ProxyManager!ProxyManager里面的方法又修改!
生命周期:
为什么需要一直与AMS进行通信?哪些操作是在AMS中进行的?其实AMS正如名字所说,管理所有的“活动”,整个系统的Activity堆栈,Activity生命周期回调都是由AMS所在的系统进程system_server帮开发者完成的;Android的Framework层帮忙完成了诸如生命周期管理等

AMSActivityThread之间对于Activity的生命周期的交互,并没有直接使用Activity对象进行交互,而是使用一个token来标识,

这个token是binder对象,因此可以方便地跨进程传递。Activity里面有一个成员变量mToken代表的就是它,token可以唯一地标识一个Activity对象,它在Activity的attach方法里面初始化;

AMS处理Activity的任务栈的时候,使用这个token标记Activity

  • Hook机制之Binder Hook
  • Hook机制之动态代理
  • Hook机制之AMS&PMS
  • Activity生命周期管理
  • 插件加载机制
  • 广播的管理方式
  • Service的插件化
  • ContentProvider的插件化
  • DroidPlugin插件通信机制
  • 插件机制之资源管理
  • 不同插件框架方案对比
  • 插件化的未来
第二阶段

Hook机制

hook,又叫钩子,通常是指对一些方法进行拦截

大致思路:

1.找到需要Hook方法的系统类

2.利用代理模式来代理系统类的运行拦截我们需要拦截的方法

3.使用反射的方法把这个系统类替换成你的代理类

大神推荐:
http://weishu.me/2016/01/28/understand-plugin-framework-overview/
分包原理
http://www.cnblogs.com/chenxibobo/p/6076459.html
http://blog.csdn.net/vurtne_ye/article/details/39666381
http://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=2649547588&idx=1&sn=71a5eaf53c601a44ddc582ef3d3de44d&scene=21#wechat_redirect

Android 插件化原理 完胜360插件框架 技术实战相关推荐

  1. 【Android 插件化】Hook 插件化框架 ( hook 插件化原理 | 插件包管理 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  2. Android插件化原理—ClassLoader加载机制

    前面<Android 插件化原理学习 -- Hook 机制之动态代理>一文中我们探索了一下动态代理 hook 实现了 启动没有在 AndroidManifest.xml 中显式声明的 Ac ...

  3. Android 插件化原理(一),通过dex文件调用插件app代码

    Android插件化原理,从以下三个问题切入: 什么是插件化 如何实现插件类的加载 如何实现插件资源的加载 什么是插件化 插件化技术最初是源于免安装运行APK的想法,这个免安装的APK就可以理解为插件 ...

  4. Android插件化原理和实践 (一) 之 插件化简介和基本原理简述

    1 插件化简介 Android插件化技术是一种这几年间非常火爆的技术,也是只有在中国才流行起来的技术,这几年间每每开发者大会上几乎都会提起关于插件化技术和相关方向.在国内各大互联网公司无不都有自己的插 ...

  5. Android 插件化原理入门笔记

    Android开发笔记 onGithub 笔记,参考7.2中所列参考文章所写,DEMO地址在PluginTestDemoApplication 1.综述 2015年是Android插件化技术突飞猛进的 ...

  6. Android 插件化原理学习 —— Hook 机制之动态代理

    前言 为了实现 App 的快速迭代更新,基于 H5 Hybrid 的解决方案有很多,由于 webview 本身的性能问题,也随之出现了很多基于 JS 引擎实现的原生渲染的方案,例如 React Nat ...

  7. 【Android 插件化】插件化原理 ( 类加载器 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  8. Android 插件化原理解析——Activity生命周期管理

    之前的 Android插件化原理解析 系列文章揭开了Hook机制的神秘面纱,现在我们手握倚天屠龙,那么如何通过这种技术完成插件化方案呢?具体来说,插件中的Activity,Service等组件如何在A ...

  9. Android 插件化原理解析——Hook机制之AMSPMS

    在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...

最新文章

  1. QLocalServer与QLocalSocket进程通讯
  2. SUSTechTripleH队墓志铭
  3. 二叉树的建立和遍历程序代码(Java,C)
  4. UVA11021麻球繁衍
  5. boost::range_result_iterator相关的测试程序
  6. oracle rman备份慢,诊断Oracle RMAN备份慢的原因
  7. Mysql 连接的使用
  8. Linux网络协议栈(三)——网络设备(1)
  9. [linux]【编译】【高级01】 - 动态库的设定和依赖性的检查 20160921更新 文章没有最终结案
  10. ajax长轮询的问题,Ajax长轮询
  11. 二、K8s Cluster详细安装步骤
  12. 基于springboot小区物业管理系统
  13. 如何设计沉浸式游戏引导界面?你要知道的七大点
  14. VMware Cloud Director 10.3.1 - 云计算调配和管理平台
  15. 硅谷的长生不老产业:炼金术 2.0,满足 CEO 们“拿钱换命”的欲望
  16. 已知两个向量的坐标求夹角的大小_两个向量的夹角怎么算
  17. 【Luat-esp32c3】4.3 文件系统——加载jpeg图片并拆包
  18. python关于q检验
  19. jq 点击按钮跳转到微信_实现点击复制微信号并自动打开微信加好友
  20. 计划处理链的很多种情况factory calendar

热门文章

  1. 线性回归2020年天猫双十一销量
  2. 云南计算机网络技术排名,2017年云南大学排名
  3. TX2(Ubuntu16.04)安装TP-link外接网卡驱动及AP热点创建
  4. Java+SSM(Spring+SpringMVC+Mybatis)个性化购物商城推荐系统 电子商务推荐系统 基于用户、项目、聚类、混合的协同过滤推荐算法WebShopRSMEx 源代码下载
  5. 《果壳中的C# C# 5.0 权威指南》 (09-26章) - 学习笔记
  6. Resource.arsc文件格式解析
  7. 【扫盲】Pulse消除马赛克(老司机福利)
  8. CentOS 7 VM虚拟机安装docker步骤
  9. SSL与数字证书,Htpps
  10. 互联网寒冬,那些不怕失业的程序员们,都有什么技能?