首页 文章 精选 留言 我的

精选列表

搜索[CLI能力],共10000篇文章
优秀的个人博客,低调大师

提升Android下内存的使用意识和排查能力

内存问题一直是大型App的开发人员比较头痛的问题,特别是像手淘这种超级的App,App中到处都是带有图片和视频的界面,而且这些功能都是由不同的团队甚至不同的事业部开发的,要整体上去管控和排查内存的问题变得相当的复杂。之前,我们多个线上版本都存在着严重的Activity等内存泄漏和不合理内存使用。这不是偶然,一个很重要的原因就是我们很多的开发测试人员侧重业务开发,忽略内存和性能,而且没有站在全局性的角度去考虑资源的使用。认为我自己的模块多缓存一些就会加快速度,以空间换时间看似正确,但是在手淘这样的超级App中是不可取的,需要严格限制,否则不要说里面几百个模块,有几十个模块这样来做,其结果都会是灾难性的,不但没有加快速度,反而会拖慢速度以及带来很多稳定性问题。 经过一年多的更新,现在的Android Studio所带的工具已经相当的成熟。以前我们还停留在使用MAT来分析内存,但是现在Android Studio的内存分析工具已经相当的强大,已经完全可以抛开MAT来实现更为直观的内存检测。我想,作为一个大型App的开发人员和测试人员,掌握这些技能都是必不可少的,也是提高整个App质量的关键所在。 在使用工具分析内存之前,我们需要了解一下内存回收上的一些策略,否则很多时候排查到的可能都不是真正的问题。 1、没有强引用不代表这块内存就会马上回收 我们知道,Java的内存回收如果有强引用存在,那么这个对象的内存不会回收。那么这个对象的引用如果不存在,是不是这块内存就会回收呢?答案是否定的,VM有自己的回收策略,不会因为一个对象的引用为空了就立马对它进行回收。也就是说,回收策略需要达到一定的触发阈值。我们可以看一个Demo,写如下的分配对象的方法: void onButtonClick(){ for (int i = 0; i < 1000; i++) { View view = new ImageView(this); } } 在内存充足的情况下,我们点击按钮4次,执行了4遍该函数,这个时候可以看到堆内存呈现了4次增长。如下图所示: 静置在那半个小时,内存仍然会维持现状,VM并不会来执行实际的GC。我们可以Dump内存看看内存中的对象: 我们可以看到,4000个ImageView对象仍然毫发无损的在内存中残留,系统没有回收其内存。不管是Dalvik还是ART环境,包括最新的Android N,都可能出现这样的情况, 具体是否每次都保持(等量)增长等还要看手机内存剩余情况和手机的GC策略 。 所以,我们在检测内存占用或者内存泄漏之前,一定要执行工具自带的GC触发功能,否则结果会不准确。明明没有泄漏或者没有占用,而Dump出来的堆中提示占用很大或者泄漏。 通过MemoryMonitor工具,我们可以看到其引用的情况。点击其中一个ImageView,我们看下它的引用情况: 可以看到,其引用路径是被一个FinalizerReference所持有。该对象已经标记为红色,表明我们自己的代码中已经没有其他引用持有该对象,状态是等待被回收。 通过手动触发GC,我们可以来主动回收这块内存,点击如下图所示的按钮,触发GC。 当然,这里还有一个问题存在,因为刚才创建的属于Finalizer对象,该对象前面的文章已经分析过,需要至少两次GC才能真正回收其内存。所以,第一次触发GC的时候,我们可以看一下内存的变化。 第一次触发GC后,内存只是部分的下降,这个时候Finalize链表中的对象被回收,但是ImageView还没有回收(在不同Rom和Android 版本下可能会存在少许差异,在Dalvik下的差异会更大一些)。我们可以看一下堆内存: 该对象的引用链路全部标记为红色,已经没有强引用指向该对象,刚才的FinalizerReference已经执行了清理。但是第一次GC只是执行了Finalizer清理,而没有真正的回收这部分对象。所以还需要再一次的触发GC,再次执行GC后,我们可以看到堆内存下降,这些对象被回收了。 我们可以通过Dump堆内存来验证是否已经回收,如下图所示,对内存中已经没有了刚才的ImageView对象,确实已经被回收了。 通过前面的分析我们可以知道,并不是引用释放了,内存就会回收。在实际使用手机淘宝的过程中,我们也可以观察堆内存的变化,在退出一个界面的时候很可能是不会有GC的,堆内存不会变化。如果这个时候用MAT工具去Dump内存,那结果很多是不够正确的。而如果后续再做其他操作,引发GC后,才会使得结果更加准确,当然我们可以手动的去触发GC。 2、调用GC时的策略变化 在前面的文章中已经提到过,代码调用GC,只是告诉VM需要GC,但是是否真正的去执行GC还是要看VM的配置和是否达到阈值。前面也提到,在执行手动GC的时候,Dalvik和ART下会有比较明显的差异。Android 5.0开始增加了更多的GC方式,到了6.0,7.0在GC方面有了更多的优化。特别是在执行Finalizer对象方面,Android 5.0开始回收就没有那么快,单次执行GC,并不会导致失去引用的Finalizer对象进行完全回收,如果要更好的回收Finalizer对象,需要执行System.runFinalization()方法来强制回收Finalizer对象。 我们将测试代码后面加上主动调用GC的代码,如下: void onButtonClick(){ for (int i = 0; i < 1000; i++) { View view = new ImageView(this); } System.gc(); } 在不同的Android版本上看下执行效果,点击按钮执行多次。在Android 4.4.4版本的设备上,内存基本已经回收,如果将1000次修改为10次,偶尔可以看到有ImageView已经没有引用存在,但是仍然没有回收。如下图所示: 从这里可以看出来,在该版本下,大部分的对象在没有强引用后,调用System.gc()就会被回收。我们再看下ART上的情况,在ART下,却发生了不一致的表现。在调用后没有进行GC。查看堆内存,我们也可以看到,4000个ImageView仍然存在,并未执行GC。 看来在ART后,这部分的GC策略做了调整,System.gc()没有内存回收。我们可以看下源码,在Android 4.4.4下的源码: /** * Indicates to the VM that it would be a good time to run the * garbage collector. Note that this is a hint only. There is no guarantee * that the garbage collector will actually be run. */ public static void gc() { Runtime.getRuntime().gc(); } 我们可以看到,在调用gc函数后,直接调用了运行时的gc。再来看下5.0上的代码: /** * Indicates to the VM that it would be a good time to run the * garbage collector. Note that this is a hint only. There is no guarantee * that the garbage collector will actually be run. */ public static void gc() { boolean shouldRunGC; synchronized(lock) { shouldRunGC = justRanFinalization; if (shouldRunGC) { justRanFinalization = false; } else { runGC = true; } } if (shouldRunGC) { Runtime.getRuntime().gc(); } } /** * Whether or not we need to do a GC before running the finalizers. */ private static boolean runGC; /** * If we just ran finalization, we might want to do a GC to free the finalized objects. * This lets us do gc/runFinlization/gc sequences but prevents back to back System.gc(). */ private static boolean justRanFinalization; /** * Provides a hint to the VM that it would be useful to attempt * to perform any outstanding object finalization. */ public static void runFinalization() { boolean shouldRunGC; synchronized(lock) { shouldRunGC = runGC; runGC = false; } if (shouldRunGC) { Runtime.getRuntime().gc(); } Runtime.getRuntime().runFinalization(); synchronized(lock) { justRanFinalization = true; } } 从源码我们可以发现,System.gc()函数,已经有了变化,从5.0开始,多了一些判断条件。是否执行gc,是依赖于justRanFinalization变量,而变量justRanFinalization在runFinalization后才会变为true。也就是说,直接调用System.gc()方法并没有调用Runtime.getRuntime().gc(),只是做了一个标记将runGC变量设置为true。 在runFinalization函数中,如果标记了runGC的,会先执行一次gc,然后清理Finalizer对象,并标记为依据清理过了Finalizer对象。这样在下次gc调用的时候,就会真正执行一次gc,以回收Finalizer对象。 在Android ART的设备上,我们将调用gc的方式做下变更: void onButtonClick(){ for (int i = 0; i < 2000; i++) { View view = new ImageView(this); } Runtime.getRuntime().gc(); } 这里直接调用了Runtime.getRuntime().gc()。这个时候内存回收确实会有变化。但是Finalizer对象仍然可能存在,在Android 5.0的时候会回收一部分,但是从6.0开始,单次调用gc,Finalizer对象却不一定回收。如下图所示,虽然所有引用链路已经不复存在,但是内存仍然没有回收: 那么执行2次gc是否就都能把内存回收了呢?我们修改下代码: void onButtonClick(){ for (int i = 0; i < 2000; i++) { View view = new ImageView(this); } Runtime.getRuntime().gc(); Runtime.getRuntime().gc(); } 这里连续2次调用了gc,按理是可以回收Finalizer对象的,但是由于两次调用gc的间隔太短,而Finalizer对象是由专门的线程执行回收的,所以也不一定能完全回收。这个和线程的调度情况有关系。例如执行上面代码可能出现的结果是部分回收: 如果想要全部回收,可以在中间停顿一些间隔,或者增加System.runFinalization()方法的调用。这样就能将当前可以回收的内存基本都回收了。我们在Android Studio的触发GC的按钮,也是通过BinderInternal$GcWatcher等代码来执行内存回收的。 当然,在实际的业务代码中,不要主动调用gc,这样可能会导致额外的内存回收开销,在检测代码中,如果需要检测内存,最好按照gc,runFinalization,gc的顺序去回收内存后,再做内存的Dump分析。 3、使用Android Studio的Memory分析内存占用 MemoryMonitor工具比起MAT一个很大的优势就是可以非常简单的查看内存占用,而且可以迅速找到自己的模块所占用的堆内存,所以希望开发和测试人员都能够迁移到Android Studio所带的工具上来。如何查看内存占用?真的是非常的简单,而且可以找到很细小的内存占用情况。 例如,这里自定义一个类,然后创建该类,代码如下: public class MyThread extends Thread{ @Override public void run() { View view = new View(MainActivity.this); view = null; } } void onButtonClick(){ new MyThread().start(); } 这里只是创建了一个该对象,但是也很容易可以跟踪到该对象的内存情况。通过MemoryMonitor的【Dump Java Heap】按钮可以把当前堆内存显示出来,如下图所示: 这里是默认查看方式,我们可以切换到以包名的形式查看。这样就可以很容易的找到我们自己的代码了。如下所示: 切换查看方式后,我们可以很容易的就找到自己所写的代码内存占用情况。这里可以看到实例的个数,占用内存的大小等情况。 例如在打开手机淘宝,简单操作一会后再来观察内存占用情况。按照包名查看后,我们很容易就可以看到整个堆内存的占用情况,如下图所示: 通过上图我们很容易看到,在com.taobao包名下占用了近240多M的内存。继续往下看,聚划算模块,图片库模块占了大头。点击ju模块,展开后,又可以看到该包名下的内存占用: 通过上图我们可以清晰的看到,在ju包名下的内存分布情况。 所以,在内存占用的检查上,Android Studio已经给我们提供了强大的工具,各个开发和测试人员已经可以很简单的查看到自己开发的模块占据的内存大小,然后对内存的使用做一些改进等措施。这里也可以通过右侧的Instance窗口检查各个实例的引用以及排查不合理的内存强制占用。 4、排查内存泄漏 Memory Dump下来后,我们可以检查Java堆的Activity内存泄漏和重复的String。很多人还习惯于MAT分析工具,其实Memory Monitor已经包含了这个功能,而且使用非常简单。 首先dump内存,如前面分析的那样,在右侧可以看到【Analyzer Tasks】按钮。 然后,我们点击该按钮,就可以看到分析泄漏的工具。 这里可以只勾选 检测泄漏Activity选项,然后选择执行。这样就可以看到泄漏的Activity了。 通过引用指向,我们可以比较容易的判断出不该持有的强引用关系,而且该工具从上到下的排序,已经做了初步的判断。 当然在检测泄漏和占用之前,需要点击2次GC的按钮,这样结果才会相对准确。 对于Android Studio提供的内存分析工具,使用起来非常简单,会比Mat工具要快捷,排查问题也更加容易。所以Android的开发和测试人员,应该尽可能的都迁移到该工具上来,并能够熟练的掌握内存分析工具,这样才能让自己开发的模块质量更加的优秀。 以上主要是针对Android Studio 2中的使用方式,在今年的Android Studio 3 Preview版本中,内存这块的分析工具更加强大,可以在面板上直接看到更细粒度的内存占用,不仅仅是Java的对内存了。 对于需要更细粒度和更全面的分析一些内存的细节,本文所涉及的内存知识还是不够的,还需要了解Linux下的内存机制以及Android下的一些内存机制,例如按页分配,共享内存,GPU内存等等。

优秀的个人博客,低调大师

“区块链”吸金能力远超云计算

区块链(Blockchain),这一被中关村区块链产业联盟理事长单位、世纪互联创始人兼董事长陈升称作互联网TCP/IP底层协议的升级版、未来网络空间基础设施新高地的新技术,将对未来的信息基础架构产生何种重要的影响? 性感,改变未来世界的商业运作模式 区块链,很多人对这一新技术并不了解,而有些人却不屑一顾,将它与比特币划上了等号。区块链确实是比特币的重要支撑技术,而比特币也是区块链技术的一种应用,但区块链技术的应用远远不止比特币这一种形式,而是在金融、公共服务、智慧城市、物联网等多个领域扮演重要角色。 区块链是一串使用密码学方法相关联产生的数据块,它提供了多中心化的、无需信任积累的信用建立范式。在这种范式中,任何互不了解的人都可以通过加入一个公开透明的数据库,通过点对点的记账、数据传输、认证或合约,而不需要借助任何一个中间方来达成信用共识。如果要给区块链技术画像,那么“全网记账”、“去中心化”、“P2P网络”、“分布式结构”等就是必不可少的几个标签。 区块链技术降低了全球信用的建立成本。这种点对点验证将会产生一种基础协议。区块链是构建未来网络空间的核心关键技术,将在网络经济、共享经济中发挥重要作用,物联网、金融、智能设备、医疗、教学、档案、司法、版权甚至家庭娱乐,都将依赖于区块链技术的发展。如果说互联网TCP/IP协议让人们进入了信息自由传递的时代,那么区块链技术就将把人们带入信息的自由公证时代。 被喻为比特币之父的中本聪在其著作中首次提到了“区块链”这一概念。比特币目前确实存在很大争议,我国的金融机构被明令禁止开展比特币业务。如今,人们对支持比特币的基础支撑技术区块链有了更深入的研究。区块链技术实际上就是一种分布式的账本技术。它的出现让公共记账成为可能,而且可以更好地支持国际支付与清算,并将改变未来世界的商业运作模式。 统计数据显示,目前在国外有900多家银行和各类机构将区块链技术应用于13个业务应用领域;在中国,也有二三十家机构将区块链技术应用于7个业务应用领域。电子钱包、支付、公共服务、资讯类服务等都已经在尝试使用区块链技术。 就像上个世纪90年代互联网技术的兴起给人们带来的震撼和改变一样,区块链这种革命性的技术将再次给人们的生活、工作带来巨变。 Factom公司正在中国努力推动区块链技术的落地。近日,Factom与软通动力联合签署合作备忘录,双方致力于将区块链技术与智慧城市解决方案进行融合。Factom公司副总裁、Factom(中国)联合创始人王立仁用“性感”一词来形容区块链技术,因为从4年前开始应用和推广区块链技术,他就发现区块链不仅将带来技术的变革,更是一个潜力巨大的商机。 区块链这种分布式记账技术通过对信息的确权,将建立起人与人之间的信任,促进信息的流通与交易,更好地实现对风险的管控。美国银行曾因欺骗性的按揭文件事件被处罚170亿美元。区块链技术的出现会让以前这种因为信息不对称而发生的金融期诈得以避免。 联盟 托起“区块链”的明天 在国际上,区块链技术受到了广泛关注,尤其是金融领域。由初创公司R3领导的区块链联盟在短短几个月中就吸收了几十家国际知名的金融机构成员。该联盟的一项核心任务是进行区块链技术的概念验证和相关技术标准的制定。不过可惜的是,R3联盟中还没有一位来自中国的成员。据说,不是中国的银行不积极,而是R3联盟已经宣布不再接纳银行成员,而是转而重点吸纳大型企业会员。 在互联网技术刚刚兴起时,由于种种原因,中国的企业没能参与主要标准的制定,丧失了话语权。那么在以区块链技术为代表的新一波互联网技术浪潮袭来时,中国不能再掉队。这也是中关村区块链产业联盟成立的重要意义所在。 应对区块链的浪潮,有几点需要注意:第一,政府要重视,因为正确运用区块链技术,可以提升公共服务的可信度,有利于共享经济的实现,更好地服务于经济发展和民生;第二,产业界要加强对区块链技术的研究,区块链是多种技术的融合,需要云计算、安全、法律,以及金融、能源、交通、医疗等行业跨技术和应用领域的联合、互动;第三,治理先行,现在已经有人将比特币用于洗黑钱,如果监管不利,有可能导致区块链被用于非法活动;第四,注重联盟,产、学、研、用等各界力量必须联合起来,共同推动区块链技术的发展和应用。 北京市东权律师事务所总经理、北京东方亿思知识产权代理有限责任公司总经理李晓冬博士也赞同以联盟的方式推动区块链产业的发展。他表示:“从技术、资金、市场推广等方面来看,一个单位或组织很难催熟区块链应用,而区块链本身所具有的去中心化、民主、自治的特征也更适合以联盟的方式进行推广。中关村区块链产业联盟是一个开放的平台,它可以让成员单位充分施展自己的才能,共同推动区块链技术标准的制定,促进产业链的发展,让所有成员受益。” 中关村区块链产业联盟虽然是一个非盈利的组织,但是推动区块链产业的发展却可以让相关参与者、推广者受益,而获益的其中一种方式就是知识产权。与国内各种各样的联盟相比,中关村区块链产业联盟的特色是推动区块链产业标准的制定,实现资源共享,通过建立专利池、版权池,反哺联盟,同时也可让联盟成员通过出售专利许可而获得收益。“推动区块链技术的发展,既需要情怀,也要重视经济利益。建立相关技术标准就和知识产权直接相关。”李晓冬表示,“中关村区块链产业联盟将参考现有的国际标准,由旗下的工作组负责具体的中国标准的制定。” 人们现在都在热烈谈论“互联网+”,让互联网与行业应用发生化学反应。其实,区块链也非常需要这个“+”。区块链可以加数字货币、金融、结算、物联网、不动产登记甚至婚姻登记。除了这些具体的应用以外,区块链更重要的是加革新的意识、新的生态系统、相关标准等。 中关村管委会郭洪主任表示:“中关村是中国的互联网发祥地、网络经济引擎和全球的互联网创新中心,也是网络强国建设的关键支撑载体。希望中关村区块链产业联盟放眼全球,抢占制高点,标准先行,创新应用,聚合区块链领域人才和资源,培育一批具有国际竞争力的区块链企业。” 云优先 区块链优先 中关村区块链产业联盟聚焦区块链技术的标准化和产业化,旨在推动未来网络空间基础设施产业快速发展,提高我国在区块链技术领域的研究、开发和应用水平,通过创新促进经济增长,为在万物互联时代下的新一轮国际竞争中抢占标准专利的制高点和话语权提供有力保障。 陈升表示:“区块链技术用共识机制确保信息真实,将推动共享经济的普及,形成与资产联接的全球开放信用体系,助力未来信息基础设施的投资、建设和运营。联盟将整合行业资源,构建核心与关健基础设施,打造面向未来的生态系统。” 区块链技术将给未来的IT基础设施建设带来哪些深远影响呢? 从最早的通信网络发展到信息网络,再到今天的价值网络,底层技术协议的改变至关重要。今天,我们在金融、支付、结算、物联网、公共服务等领域看到的因区块链技术带来的变化只是“冰山一角”。“为了提供中立、安全、公共化、服务化的基础设施,我们需要像区块链这样的新技术。”陈升表示。 作为一家IDC服务商,提供安全、可靠、高效、整体拥有成本最优的数据中心基础设施是世纪互联的主业。世纪互联集团公司创新研究院将致力于区块链技术的研发。在国内,微软与世纪互联在云数据中心的建设和云服务的提供方面有全面而深入的合作。微软在Azure云平台上已经开始提供“区块链即服务”(Blockchain as a Service)。下一步,微软计划将这一服务引入中国,而合作伙伴还是选择世纪互联。这也是“云优先、区块链优先”的具体体现。 “互联网虽然解决了安全、低成本的信息传递问题,但是没有解决价值有效传递这一问题。因此,区块链应运而生,它不是替代现有的互联网,而是在其上增加了‘有价值’的一层。”点亮投资管理(上海)有限公司合伙人郭峰介绍说,“就像网络分不同的层面,区块链也分成三个层面:最底层是基于TCP/IP的P2P网络;中间层包括密码学算法和分布式共识算法,以及平台的路由,这一层也是实现互联网价值传递的基础;最上层是各种应用。” 区块链是多种技术的组合,涉及不同的架构、场景,而且变化非常快,它更需要可靠、廉价、易扩展的基础设施。未来,很多终端和应用都可以由区块链来支撑,比如智能手环、手机等。 华旗银行与日本的野村证券做过一项研究:使用区块链技术的银行可以将运营成本降低到原来的十分之一甚至更低。“区块链技术的应用可以极大地节省社会资源。”郭峰表示,“在国外,针对区块链技术公司的投资热度远远超过了云计算。“ 记者获悉,近日,美国一家金融科技公司Ripple的高管到访中国。这家成立于2012年的公司基于区块链技术提供跨境支付服务,此次来华也是想在中国寻找落地其服务的机会。另外,像IBM这样的IT巨头也表示出对区块链技术的浓厚兴趣。 本文转自d1net(转载)

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册