深入探索Android内存优化(炼狱级别下)成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我

如果你对以上基础内容都比较了解了,那么我们便开始Android内存优化的探索之旅吧。

内存达到阈值后自动触发HprofDump,将得到的Hprof存档后由人工通过MAT进行分析。

检测和分析报告都在一起,批量自动化测试和事后分析都不太方便。

目前,它的主要功能有三个部分,如下所示:

方便通过减少冗余Bitmap的数量,以降低内存消耗。

在研发阶段需要不断实现更多的工具和组件,以此系统化地提升自动化程度,以最终提升发现问题的效率。

除了常用的内存分析工具MemoryProfiler、MAT、LeakCanary之外,还有一些其它的内存分析工具,下面我将一一为大家进行介绍。

接下来,我们输入以下命令查看top命令的用法:

quchao@quchaodeMacBook-Pro~%adbshelltop--helpusage:top[-Hbq][-kFIELD,][-oFIELD,][-sSORT][-nNUMBER][-dSECONDS][-pPID,][-uUSER,]Showprocessactivityinrealtime.-H Showthreads-k FallbacksortFIELDS(default-S,-%CPU,-ETIME,-PID)-o ShowFIELDS(defPID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)-O AddFIELDS(replacingPR,NI,VIRT,RES,SHR,Sfromdefault)-s Sortbyfieldnumber(1-X,default9)-b Batchmode(notty)-d DelaySECONDSbetweeneachcycle(default3)-n ExitafterNUMBERiterations-p ShowthesePIDs-u ShowtheseUSERs-q Quiet(noheaderlines)CursorLEFT/RIGHTtochangesort,UP/DOWNmovelist,spacetoforceupdate,Rtoreversesort,Qtoexit.这里使用top仅显示一次进程信息,以便来讲解进程信息中各字段的含义。

前四行是当前系统情况整体的统计信息区。下面我们看每一行信息的具体意义。

具体信息说明如下所示:

系统现在共有729个进程,其中处于运行中的有1个,715个在休眠(sleep),stoped状态的有0个,zombie状态(僵尸)的有8个。

具体信息如下所示:

具体属性说明如下所示:

对于内存监控,在top里我们要时刻监控第三行swap交换分区的used,如果这个数值在不断的变化,说明内核在不断进行内存和swap的数据交换,这是真正的内存不够用了。

在第五行及以下,就是各进程(任务)的状态监控,项目列信息说明如下所示:

在讲解dumpsysmeminfo命令之前,我们必须先了解下Android中最重要的四大内存指标的概念,如下表所示:

从上可知,它们之间内存的大小关系为VSS>=RSS>=PSS>=USS。

RSS与PSS相似,也包含进程共享内存,但比较麻烦的是RSS并没有把共享内存大小全都平分到使用共享的进程头上,以至于所有进程的RSS相加会超过物理内存很多。而VSS是虚拟地址,它的上限与进程的可访问地址空间有关,和当前进程的内存使用关系并不大。比如有很多的map内存也被算在其中,我们都知道,file的map内存对应的可能是一个文件或硬盘,或者某个奇怪的设备,它与进程使用内存并没有多少关系。

而PSS、USS最大的不同在于“共享内存“(比如两个App使用MMAP方式打开同一个文件,那么打开文件而使用的这部分内存就是共享的),USS不包含进程间共享的内存,而PSS包含。这也造成了USS因为缺少共享内存,所有进程的USS相加要小于物理内存大小的原因。

最早的时候官方就推荐使用PSS曲线图来衡量App的物理内存占用,而Android4.4之后才加入USS。但是PSS,有个很大的问题,就是”共享内存“,考虑一种情况,如果A进程与B进程都会使用一个共享SO库,那么So库中初始化所用掉的那部分内存就会平分到A与B的头上。但是A是在B之后启动的,那么对于B的PSS曲线而言,在A启动的那一刻,即使B没有做任何事情,也会出现一个比较大的阶梯状下滑,这会给用曲线图分析软件内存的行为造成致命的麻烦。

USS虽然没有这个问题,但是由于Dalvik虚拟机申请内存牵扯到GC时延和多种GC策略,这些都会影响到曲线的异常波动。例如异步GC是Android4.0以上系统很重要的特性,但是GC什么时候结束?曲线什么时候”降低“?就无法预计了。还有GC策略,什么时候开始增加Dalvik虚拟机的预申请内存大小(Dalvik启动时是有一个标称的start内存大小,它是为Java代码运行时预留的,避免Java运行时再申请而造成卡顿),但是这个预申请大小是动态变化的,这一点也会造成USS忽大忽小。

了解完Android内存的性能指标之后,下面我们便来说说dumpsysmeminfo这个命令的用法,首先我们输入adbshelldumpsysmeminfo-h查看它的帮助文档:

quchao@quchaodeMacBook-Pro~%adbshelldumpsysmeminfo-hmeminfodumpoptions:[-a][-d][-c][-s][--oom][process]-a:includeallavailableinformationforeachprocess.-d:includedalvikdetails.-c:dumpinacompactmachine-parseablerepresentation.-s:dumponlysummaryofapplicationmemoryusage.-S:dumpalsoSwapPss.--oom:onlyshowprocessesorganizedbyoomadj.--local:onlycollectdetailslocally,don'tcallprocess.--package:interpretprocessargaspackage,dumpingallprocessesthathaveloadedthatpackage.--checkin:dumpdataforacheckinIf[process]isspecifieditcanbethenameorpidofaspecificprocesstodump.接着,我们之间输入adbshelldumpsysmeminfo命令:

此外,为了查看单个App进程的内存信息,我们可以输入如下命令:

如果Views与Activities、AppContexts持续上升,则表明有内存泄漏的风险。

LeakInspector是腾讯内部的使用的一站式内存泄漏解决方案,它是Android手机经过长期积累和提炼、集内存泄漏检测、自动修复系统Bug、自动回收已泄露Activity内资源、自动分析GC链、白名单过滤等功能于一体,并深度对接研发流程、自动分析责任人并提缺陷单的全链路体系。

它们之间主要有四个方面的不同,如下所示:

它们都支持对Activity、Fragment及其它自定义类的泄漏检测,但是,LeakInspector还增加了Btiamp的检测能力,如下所示:

这一个部分的实现原理,我们可以采用ARTHook的方式来实现,还不清楚的朋友请再仔细看看大图检测的部分。

两个工具的泄漏检测原理都是在onDestroy时检查弱引用,不同之处在于LeakInspector直接使用WeakReference来检测对象是否已经被释放,而LeakCanary则使用ReferenceQueue,两者效果是一样的。

并且针对Activity,我们通常都会使用Application的registerActivityLifecycleCallbacks来注册Activity的生命周期,以重写onActivityDestroyed方法实现。但是在Android4.0以下,系统并没有提供这个方法,为了避免手动在每一个Activity的onDestroy中去添加这份代码,我们可以使用反射Instrumentation来截获onDestory,以降低接入成本。代码如下所示:

这里的白名单是为了处理一些系统引起的泄漏问题,以及一些因为业务逻辑要开后门的情形而设置的。分析时如果碰到白名单上标识的类,则不对这个泄漏做后续的处理。二者的配置差异有如下两点:

针对系统泄漏,LeakInspector通过反射自动修复了目前碰到的一些系统泄漏,只要在onDestory里面调用一个修复系统泄漏的方法即可。而LeakCanary虽然能识别系统泄漏,但是它仅仅对该类问题给出了分析,没有提供实际可用的解决方案。

如果检测到发生了内存泄漏,LeakInspector会对整个Activity的View进行遍历,把图片资源等一些占内存的数据释放掉,保证此次泄漏只会泄漏一个Activity的空壳,尽量减少对内存的影响。代码大致如下所示:

if(ViewinstanceofImageView){//ImageViewImageButton处理recycleImageView(app,(ImageView)view);}elseif(viewinstanceofTextView){//释放TextView、Button周边图片资源recycleTextView((TextView)view);}elseif(ViewinstanceofProgressBar){recycleProgressBar((ProgressBar)view);}else{if(viewinstancofandroid.widget.ListView){recycleListView((android.widget.ListView)view);}elseif(viewinstanceofandroid.support.v7.widget.RecyclerView){recycleRecyclerView((android.support.v7.widget.RecyclerView)view);}elseif(viewinstanceofFrameLayout){recycleFrameLayout((FrameLayout)view);}elseif(viewinstanceofLinearLayout){recycleLinearLayout((LinearLayout)view);}if(viewinstanceofViewGroup){recycleViewGroup(app,(ViewGroup)view);}}这里以recycleTextView为例,它回收资源的方式如下所示:

privatestaticvoidrecycleTextView(TextViewtv){Drawable[]ds=tv.getCompoundDrawables();for(Drawabled:ds){if(d!=null){d.setCallback(null);}}tv.setCompoundDrawables(null,null,null,null);//取消焦点,让Editor$Blink这个Runnable不再被post,解决内存泄漏。tv.setCursorVisible(false);}三、后期处理不同1、分析与展示采集dump之后,LeakInspector会上传dump文件,并*调用MAT命令行来进行分析*,得到这次泄漏的GC链。而LeakCanary则用开源组件HAHA来分析得到一个GC链。但是LeakCanary得到的GC链包含被hold住的类对象,一般都不需要用MAT打开Hporf即可解决问题。而LeakInpsector得到的GC链只有类名,还需要MAT打开Hprof才能具体去定位问题,不是很方便。

LeakInspector在dump分析结束之后,会提交缺陷单,并且把缺陷单分配给对应类的负责人。如果发现重复的问题则更新旧单,同时具备重新打开单等状态转换逻辑。而LeakCanary仅会在通知栏提醒用户,需要用户自己记录该问题并做后续处理。

LeakInspector跟自动化测试可以无缝结合,当自动化脚本执行中发现内存泄漏,可以由它采集dump并发送到服务进行分析,最后提单,整个流程是不需要人力介入的。而LeakCanary则把分析结果通过通知栏告知用户,需要人工介入才能进入下一个流程。

JHat是Oracle推出的一款Hprof分析软件,它和MAT并称为Java内存静态分析利器。不同于MAT的单人界面式分析,jHat使用多人界面式分析。它被内置在JDK中,在命令行中输入jhat命令可查看有没有相应的命令。

启动服务器后,我们打开入口地址127.0.0.1:7000即可查看AllClasses界面,如下图所示:

jHat还有两个比较重要的功能,分别如下所示:

打开127.0.0.1:7000/histo/,统计表界面如下所示:

可以到,按TotalSize降序排列了所有的Class,并且,我们还可以查看到每一个Class与之对应的实例数量。

OQL是一种模仿SQL语句的查询语句,通常用来查询某个类的实例数量,打开127.0.0.1:7000/oql/并输入java.lang.String查询String实例的数量,结果如下图所示:

JHat比MAT更加灵活,且符合大型团队安装简单、团队协作的需求。但是,并不适合中小型高效沟通型团队使用。

GC产生的原因有如下九种:

GC类型有如下三种:

GC采集的方法有如下四种:

通过GC日志,我们可以知道GC的量和它对卡顿的影响,也可以初步定位一些如主动调用GC、可分配的内存不足、过多使用WeakReference等问题。

对于HTML5页面而言,抓取JavaScript的内存需要使用ChromeDevtools来进行远程调试。方式有如下两种:

Android4.4及以上系统的原生浏览器就是Chrome浏览器,可以使用ChromeDevtool远程调试WebView,前提是需要在App的代码里把调试开关打开,如下代码所示:

这里总结一下JS中几种常见的内存问题点:

在我们进行内存优化的过程中,有许多内存问题都可以归结为一类问题,为了便于以后快速地解决类似的内存问题,我将它们归结成了以下的多个要点:

解决方案是在Activity关闭,即触发onDestory时解除内类和外部的引用关系。

这也是一个this$0间接引用的问题,对于Handler的解决方案一般可以归结为如下三个步骤:

这里需要在使用过程中注意对WeakReference进行判空。

我们通常都会使用getSystemService方法来获取系统服务,但是当在Activity中调用时,会默认把Activity的Context传给系统服务,在某些不确定的情况下,某些系统服务内部会产生异常,从而hold住外界传入的Context。

解决方案是直接使用Applicaiton的Context去获取系统服务。

我们都知道,对应WebView来说,其网络延时、引擎Session管理、Cookies管理、引擎内核线程、HTML5调用系统声音、视频播放组件等产生的引用链条无法及时打断,造成的内存问题基本上可以用”无解“来形容。

解决方案是我们可以把WebView装入另一个进程。具体为在AndroidManifes中对当前的Activity设置android:process属性即可,最后,在Activity的onDestory中退出进程,这样即可基本上终结WebView造成的泄漏。

我们在平常开发过程中经常需要在Activity创建的时候去注册一些组件,如广播、定时器、事件总线等等。这个时候我们应该在适当的时候对组件进行注销,如onPause或onDestory方法中。

不仅在使用Handler的sendMessage方法时,我们需要在onDestory中使用removeCallbackAndMessage移除回调和消息,在使用到Handler/FrameLayout的postDelyed方法时,我们需要调用removeCallbacks去移除实现控件内部的延时器对Runnable内类的持有。

在做资源适配的时候,因为需要考虑到APK的瘦身问题,无法为每张图片在每个drawable/mipmap目录下安置一张适配图片的副本。很多同学不知道图片应该放哪个目录,如果放到分辨率低的目录如hdpi目录,则可能会造成内存问题,这个时候建议尽量问设计人员要高品质图片然后往高密度目录下方,如xxhdpi目录,这样在低密屏上”放大倍数“是小于1的,在保证画质的前提下,内存也是可控的。也可以使用Drawable.createFromSream替换getResources().getDrawable来加载,这样便可以绕过Android的默认适配规则。

对于已经被用户使用物理“返回键”退回到后台的进程,如果包含了以下两点,则不会被轻易杀死。

我们应该在item被回收不可见时去释放掉对图片的引用。如果你使用的是ListView,由于每次item被回收后被再次利用都会去重新绑定数据,所以只需在ImageView回调其onDetchFromWindow方法的时候区释放掉图片的引用即可。如果你使用的是RecyclerView,因为被回收不可见时第一次选择是放进mCacheView中,但是这里面的item被复用时并不会去执行bindViewHolder来重新绑定数据,只有被回收进mRecyclePool后拿出来复用才会重新绑定数据。所以此时我们应该在item被回收进RecyclePool的时候去释放图片的引用,这里我们只要去重写Adapter中的onViewRecycled方法就可以了,代码如下所示:

@OverridepublicvoidonViewRecycled(@NullableVHholder){super.onViewRecycled(holder);if(holder!=null){//做释放图片引用的操作}}10、使用ViewStub进行占位我们应该使用ViewStub对那些没有马上用到的资源去做延迟加载,并且还有很多大概率不会出现的View更要去做懒加载,这样可以等到要使用时再去为它们分配相应的内存。

产品或者运营为了统计数据会在每个版本中不断地增加新的埋点。所以我们需要定期地去清理一些过时的埋点,以此来适当地优化内存以及CPU的压力。

我们在做子线程操作的时候,喜欢使用匿名内部类Runnable来操作。但是,如果某个Activity放在线程池中的任务不能及时执行完毕,在Activity销毁时很容易导致内存泄漏。因为这个匿名内部类Runnable类持有一个指向Outer类的引用,这样一来如果Activity里面的Runnable不能及时执行,就会使它外围的Activity无法释放,产生内存泄漏。从上面的分析可知,只要在Activity退出时没有这个引用即可,那我们就通过反射,在Runnable进入线程池前先干掉它,代码如下所示:

Fieldf=job.getClass().getDeclaredField("this$0");f.setAccessible(true);f.set(job,null);这个任务就是我们的Runnable对象,而”this$0“就是上面所指的外部类的引用了。这里注意使用WeakReference装起来,要执行了先get一下,如果是null则说明Activity已经回收,任务就放弃执行。

我们发现我们的APP在内存方面可能存在很大的问题,第一方面的原因是我们的线上的OOM率比较高。

第二点呢,我们经常会看到在我们的AndroidStudio的Profiler工具中内存的抖动比较频繁。

这是我们一个初步的现状,然后在我们知道了这个初步的现状之后,进行了问题的确认,我们经过一系列的调研以及深入研究,我们最终发现我们的项目中存在以下几点大问题,比如说:内存抖动、内存溢出、内存泄漏,还有我们的Bitmap使用非常粗犷。

比如内存抖动的解决=>MemoryProfiler工具的使用(呈现了锯齿张图形)=>分析到具体代码存在的问题(频繁被调用的方法中出现了日志字符串的拼接),也可以说说内存泄漏或内存溢出的解决。

为了不增加业务同学的工作量,我们使用了一些工具类或ARTHook这样的大图检测方案,没有任何的侵入性。同时,我们将这些技术教给了大家,然后让大家一起进行工作效率上的提升。

我们一开始并没有直接去分析项目中代码哪些地方存在内存问题,而是先去学习了Google官方的一些文档,比如说学习了MemoryProfiler工具的使用、学习了MAT工具的使用,在我们将这些工具学习熟练之后,当在我们的项目中遇到内存问题时,我们就能够很快地进行排查定位问题进行解决。

一开始,我们做了整体APP运行阶段的一个内存上报,然后,我们在一些重点的内存消耗模块进行了一些监控,但是,后面发现这些监控并没有紧密地结合我们的业务代码,比如说在梳理完项目之后,发现我们项目中存在使用多个图片库的情况,多个图片库的内存缓存肯定是不公用的,所以导致我们整个项目的内存使用量非常高。所以进行技术优化时必须结合我们的业务代码。

我们在做内存优化的过程中,不仅做了Android端的优化工作,还将我们Android端一些数据的采集上报到了我们的服务器,然后传到我们的APM后台,这样,方便我们的无论是Bug跟踪人员或者是Crash跟踪人员进行一系列问题的解决。

比如说大图片的检测,我们最初的一个方案是通过继承ImageView,重写它的onDraw方法来实现。但是,我们在推广它的过程中,发现很多开发人员并不接受,因为很多ImageView之前已经写过了,你现在让他去替换,工作成本是比较高的。所以说,后来我们就想,有没有一种方案可以免替换,最终我们就找到了ARTHook这样一个Hook的方案。

对于内存优化的专项优化而言,我们要着重注意两点,即优化大方向和优化细节。

对于优化的大方向,我们应该优先去做见效快的地方,主要有以下三部分:

对于优化细节,我们应该注意一些系统属性或内存回调的使用等等,主要可以细分为如下六部分:

最后,当监控到应用内存超过阈值时,还定制了完善的兜底策略来重启应用进程。

总的来看,要建立一套全面且成体系的内存优化及监控是非常重要也是极具挑战性的一项工作。并且,目前各大公司的内存优化体系也正处于不断演进的历程之中,其目的不外乎:实现更健全的功能、更深层次的定位问题、快速准确地发现线上问题。

THE END
1.华为手机的文件夹华为手机的文件夹在哪里? 华为手机的文件夹位于【文件管理】APP中。首先打开华为手机系统自带的【文件管理】APP,然后点击底部【分类】,接着再点击【内部存储】,就可以看到文件夹了。最后选择你要找的文件即可。如果你找不到文件管理,可以通过向右滑动手机屏幕到负一屏,在负一屏的搜索框内输入“文件管理”,点击搜索结果http://www.mymach.cn/ds/gwq11q631.html
2.计算机软件毕业设计基于Android系统的课程表的【计算机软件毕业设计】基于Android系统的课程表的设计与实现 https://bbs.pinggu.org/thread-13236406-1-1.html
3.手机版的腾讯课堂的离线视频缓存在那个文件夹?找到离线视频缓存可能需要一些技术操作,你可以尝试打开文件管理器,进入应用或者下载目录,然后查找名为Tencent Classroom或.tncache的子文件夹,那里应该藏着你的离线视频数据。如果不确定怎么找,可以试试重启手机后查看是否有变化 有用(0) 回复 原來你也在這里 腾讯课堂的离线视频缓存通常会保存在你的手机内部存储空间https://wap.zol.com.cn/ask/x_1053610.html
4.目录竞争性谈判文件 项目编号:0773-2241GZZC098 目录 一,竞争性谈判公告 1 三,竞争性谈判程序 12 四,竞争性谈判验证及内容 https://ggzy.guizhou.gov.cn/hallweb/hall/attach/nosession/download?attachId=8a8bb7d584b38df90184d1afdb7f311e
5.安徽省网络课程学习中心(e会学)用户协议此外,您同意不抓取和批量下载本产品的内容,包括但不限于系统上的用户列表或目录、在线教材、用户发布内容或用户信息。在使用本产品时,您不得冒用或者试图冒用他人身份。 用户帐号和权限 为了充分参与本产品的各项活动,您必须提供姓名、手机号、电子邮件地址和用户密码才能创建用户帐号(下称“用户帐号”)。若适用的法律https://app2021.ehuixue.cn/appnotice.html
6.车载Androidauto测试用例车载app测试9:adb shell top -m 5 (查看占用手机前五的应用) 10:adb shell top -n 1 刷星一次内存信息,原后返回 11:adb shell chmod设置文件权限 12:adb shell mkdir 新建文件目录 13:adb shell cat 查看文件内容 14:/proc/cpuinto 此文件存放硬件信息 https://blog.51cto.com/u_16213686/11656008
7.怎样下载网易云课堂视频4 4登录完成后,打开正在学的课程,点击选择右上角的下载图标进入下载页面。5 5选中要下载的课程章节,然后点击"确定下载"开始下载视频缓存。6 6下载完成后,我们就可以不需要使用手机流量,直接离线观看学习视频课程,看完后,为了不占用手机内存,也可以在此处删除视频,即:选定后再点击 垃圾桶可删除视频。https://jingyan.baidu.com/article/6b18230900bf14fa59e1595d.html
8.单招十类(计算机基础)知识点整理备考版本嵌入式计算机:嵌入在各种设备中,如智能手机、汽车电子、家用电器等。 按性能和功能分类: 主机:指大型计算机系统中的主要计算和处理单元。 工作站:用于科学和工程计算,具备较高性能和图形处理能力。 微型计算机:通常指个人计算机,用于个人日常任务和办公应用。 https://www.jianshu.com/p/be5f3482db0f
9.S60V3一些基本设置及常见的问题解决方法!注意:手机出厂自带软件无法删除 内存卡里的目录分析 QUOTE: Data\mbook 掌上书院安装后配置文件存放文件夹,如果遇到书打不开可以把其中的umdrcnt.lst,umdstng删掉,再打开 Images 照片图片存放位置 Installs 存放安装文件 Music Downloads 机子自带浏览器下载音乐后,都存在这里 https://www.360doc.cn/article/20425_717425.html
10.GitHubcucy/pysparkWe read every piece of feedback, and take your input very seriously. Include my email address so I can be contacted Cancel Submit feedback Saved searches Use saved searches to filter your results more quickly Cancel Create saved search Sign in Sign up Reseting focus {https://github.com/cucy/pyspark_project
11.新晋黑马神器!Figma完全入门指南(附超多插件+教程)优设网目录总览 前言 我为什么要说Figma,最直观的感受就是,这个工具真的非常好用,使用起来非常流畅。可以提高设计效率,用起来很爽,然后想分享给大家 最重要的是,Figma已经成为主流原型设计工具,为什么这么说?我们来看一份来自UXTOOLS调查2019年的设计工具使用报告(2020年Figma的用户应该会更多),报告详情请查看:https://uxhttps://www.uisdc.com/figma-complete-guide/
12.芒果tv离线缓存怎么设置芒果tv手机版离线缓存设置教程很多人想知道芒果tv离线缓存放在哪里?手机内存上还是内存卡上。今天小编就为大家带来芒果tv手机版离线缓存设置教程和存放地址,感兴趣的朋友一起去看下吧。 芒果TV客户端播放器PC软件 v6.7.20.0 官方安装电脑版 类型:网络电视 大小:76.8MB 语言:简体中文 https://www.jb51.net/softjc/306157.html
13.出门不带手机跑步,试试荣耀手表4所以,如果购入的第一块运动手表,能进行离线支付,方便跑步者随时在各个补给点,购买水和食物,就再好不过了。我个人的习惯是不带手机出门跑步,这样跑起来也更加轻松,减轻运动负担,但这样也会遇到有人紧急联系我,而找不到人的情况。所以,我认为购买一款具备独立eSIM电话功能的运动手表还是很有必要的,轻松畅跑的同时,https://zhuanlan.zhihu.com/p/643902911
14.2021届计算机科学方向毕业设计(论文)阶段性汇报目前已完成近数据计算内存分配函数的设计和相关仿真环境的搭建,并获得近数据计算系统在图像处理、高性能计算应用场景下的仿真测试结果。本次汇报将分析图像处理和高性能计算应用场景下的实验结果。下一阶段将完善图计算应用场景下的仿真实验,并开始撰写毕业论文。 陈伟哲 面向多智能体强化学习的自动课程学习的研究 这https://zhiyuan.sjtu.edu.cn/html/zhiyuan/announcement_view.php?id=3943
15.Java课程列表盘符: cd 目录 cd … cd 目录\目录\目录 cd \ cls exit 二、基础_JavaSE_02_注释、关键字、常量、输出语句、数据类型、变量 课程回顾 1.注释: 单行注释(//) 快捷键: Ctrl+/ 多行注释(/* */) 快捷键: Ctrl+Shift+/ Ctrl+Shift+\ 文档注释(/** */) https://blog.csdn.net/hdy989/article/details/114500423
16.图片浏览App排行榜魅族手机图片浏览app推荐课程表等模板-打开13种表格格式文档,包括加密文档 -公式输入编辑器,解决手机输入法输入函数难的问题-商务合同等 -支持 OFD 文档打印 -支持查看 OFD 文档信息/缩略图/目录/语义目前支持安卓版13.4版本及W浏览器,是市场上极简极省用户手机内存的浏览器,没有用户不需要的无关信息,页面完全自定制,让您的网络https://www.diandian.com/phb/1856/6-1.html
17.福州公共资源交易网(台) 否 1、 设备高度≤1.5U,采用≥四核处理器 ,主频≥1.4GHZ,内置内存≥2GB、≥128G SSD硬盘 2同时支持文件拖拽特定区域自动加载目录功能,无需手动查找目录,传输文件大小无限制,任意大小文件都可进行https://fzsggzyjyfwzx.cn/jyxxcggg/681737.jhtml