语言android 内存泄露调试

一、概述 1

本文目标在于记录在FreeCAD源码阅读着打探及的一部分事物。

次、Android(Java)中广大的善招内存泄漏的破代码 1

FreeCAD编译

FreeCAD源码的编译最好使用官方提供的LibPack,否则第三方库难以找寻全,找到后还索要团结编译,此外尚非清楚CMake是否能够那么顺找好(find_package)自己若的老三方库。采用官方提供的LibPack可以排这等同老堆的辛苦。但是官方的LibPack仅发生提供针对性VS2008,
VS2013,
VS2012x64底版,分别可以在FreeCAD在github上之发表地方0.16同0.15本位置找到(VC9,
VC12),而sourceforge地址还可找到x64的VS2012。

本人下的LibPack是FreeCADLibs_11.0_x64_VC11.7z本,这个本在boost_python上发lib和dll缺失,可以打boost官方预编译版本1.55.0本拷贝x64员相应的lib和dll,也可于FreeCADLibs_10.0_x64_VC11.7z里面把4只文本拷贝出来。

源码采用0.16底,没有采用0.17_pre,目标重点在编译出来看,没有失去追求官方最新的本。解压source,LibPack默认是暨源码放置同一目录的,如果如放于不同之目,可以用CMakeLists.txt第125行set(FREECAD_LIBPACK_DIR
${CMAKE_SOURCE_DIR} CACHE PATH “Directory of the FreeCAD
LibPack”)中的${CMAKE_SOURCE_DIR}改为${CMAKE_BINARY_DIR},cmake-gui.exe可以健全通过。

(一) 查询数据库没有关闭游标 2

其三正库粗略记录

并未列举齐全的老三方库表格如下:

Lib Name version in LibPack_11.0_x64_VC11 Link to get it
Python Python 2.7.8 http://www.python.org/
PySide 1.2.2 http://wiki.qt.io/PySide
shiboken 1.2.2 http://shiboken.readthedocs.io/en/latest/
Qt Qt 4 https://www.qt.io/
Boost 1.55.0 http://www.boost.org/
Coin3D 4.0 https://bitbucket.org/Coin3D/coin/wiki/Home
SoQt 1.2 https://bitbucket.org/Coin3D/soqt
OpenCASCADE oce-16(对应6.7.1) http://www.opencascade.com

当以上第三在库中,PySide是Python与Qt的休戚与共,可以下Python语言构建Gui。建议是以Python2.7多重中行使,支持部分Python3,与PySide有同效果的PyQt相对成熟有,但商用需要付费,估计这是FreeCAD采用PySide的缘故,PySide是Qt官方发之,完成了针对性Qt4.8本子的圆兑现,支持Qt5的PySide2也可以以github中找到。shiboken作何用途,我还不曾将得稀亮。

FreeCAD对Python是重度依赖,不可知不够。如果协调来下手第三方库,就亟须先行动手定Python,PySide,Boost,shiboken,所以采用官方提供的LibPack是足以省去成千上万劳动的。

(二) 构造Adapter时,没有采用缓存的 convertView 3

工程项目的简要分析

可以将FreeCAD_trunk.sln目录之下的花色分为两近乎,一接近为
FreeCAD打头的根基工程项目;另一样类似为Mod模块工程。基础工程项目列表如下:

工程项目 产生文件 备注
FreeCADMain FreeCAD.exe FreeCAD主执行启动文件,main()函数所在地
FreeCADMainPy FreeCAD.pyd 兼容Python的扩展dll,导出initFreeCAD()
FreeCADMainCmd FreeCADCmd.exe App::Application::Config()["RunMode"]有三种模式,Gui、Exit、Console,这里对应的是Exit模式,执行(argc, argv)之后自动退出
FreeCADGui FreeCADGui.dll 命名空间Gui,Command,Workbench,View3dInventor(视图),Gui层的Document
FreeCADGuiPy FreeCADGui.pyd 兼容Python的扩展dll
FreeCADBase FreeCADBase.dll 代码基础与上层,命名空间Base,Type类型体系,InterpreterSingleton脚本解释器
FreeCADApp FreeCADApp.dll 表征exe执行所在的应用,命名空间App,App::GetApplication()可以获取唯一的那个pcSingleton指针,App层Document

以上这些就建构了FreeCAD运行的根基框架,它们其实只是使用了Python, Boost,
PySide, shiboken, xerces-c, zlib,
coin3d等这些,其余的Mod都是模块扩展,依赖诸如OCE,PCL,Eigen3,libqhull等等,每个Mod工程项目分为带Gui的及无带Gui的本。带Gui的花色概念了可用之Command,Workbench(工作台),显示等这些。

就此FreeCAD对Python依赖如此的大,是为精神上FreeCAD所有的命实现都是透过Python语句来落实之。比如一个Box的创导命令是这样的:

C++
void CmdPartBox::activated(int iMsg)
{
    QString cmd;
    cmd = qApp->translate("CmdPartBox","Cube");
    openCommand((const char*)cmd.toUtf8());

    doCommand(Doc,"App.ActiveDocument.addObject(\"Part::Box\",\"Box\")");
    cmd = QString::fromLatin1("App.ActiveDocument.ActiveObject.Label = \"%1\"")
        .arg(qApp->translate("CmdPartBox","Cube"));
    doCommand(Doc,(const char*)cmd.toUtf8());
    commitCommand();
    updateActive();
    doCommand(Gui, "Gui.SendMsgToActiveView(\"ViewFit\")");
}

里头这些都是发送给解释器的Python语句呀,执行后会于界面及之Python
Console窗口播报Python执行语句,这样录制宏就简单极了,此外也得通下Python来建模或者写单力量实现,比如就起个SheetMetal就完全是用Python来实现。

Command命令的对象是生NewObject加入Document,特征附有属性,然后recompute()执行计算,这样虽可以重生成,响应修改属性的结果。

(三) Bitmap对象不在以时调用recycle()释放内存 4

fcstd文件格式分析

fcstd是FreeCAD存储下来的文件,这个格式实际上就是zip压缩文件,可以改后缀成为zip或者直接拖拽到巧打开的WinRAR可以看来中的文件,简单的讲话就是4只,多之话语数量不掉。其中Document.xml是对承诺FreeCADApp里边的Doc,GuiDocument.xml对许FreeCADGui里边的Doc,另外有PartShape.brp文件就是OpenCASCADE官方的brep格式呀。

(四) 释放对象的援 4

Sketcher草图

因此说草图,是发现FreeCAD的草图看起还不易,实时可见(不同让实体的创立),可以捕捉到丝段的端点,中点,两久线之交点等这些。

  • CmdSketcherCreateLine
    是草图绘制线段的吩咐,该令于激活时会见调用ActivateHandler(getActiveGuiDocument(),
    new
    DrawSketchHandlerLine())将此handler交给SketcherGui::ViewProviderSketch激活
  • DrawSketchHandlerLine 派生自
    DrawSketchHandler,会产生个mouseMove()的函数重载定义鼠标行为,并调用seekAutoConstraint(),
    renderSuggestConstraitsCursor()
  • App里边生只planegcs文件夹,里边好针对约束求解,代码稍微有点多没有细看,相比D-Cubed怎么样就非知道了

(五) 其他 5

关于BUILD_JTREADER

因作者对JT格式做过分析,发现FreeCAD里边有这个选项,就特别留心了转。需要提醒的是BUILD_JTREADER在是本子无效,因为src/Mod下边没有JtReader文件夹,0.17_pre里边也没,但是github最新版本的源码里发欠文件夹。略略地圈了瞬间,实现好简单,跳了不少物,相比OpenCASCADE官方提供的TKJT弱很多(不过OCC的TKJT也大漫长没更新了,一更新就顶了急需付费可以得到里去了)。不过FreeCAD还时有发生个JTREADER.h文件,调用了JtOpen的头文件呀,这个牛,可惜JtOpen试用版一般只来一个月吧。

其三、内存监测工具 DDMS –> Heap 5

小结

2017/12/22
FreeCAD架构体系要十分清晰的,也实现了许多中心(比如Undo/Redo,参数化,自动保存等),模块也揽很多;Python嵌入好坏不好评价,但自我个人小习惯。总的来说给自身之感觉到是勿精。

季、内存分析工具 MAT(Memory Analyzer Tool) 7

(一) 生成.hprof文件 7

(二) 使用MAT导入.hprof文件 8

(三) 使用MAT的视图工具分析内存 8

 

 

一、概述

    Java编程中时容易让忽略,但本身又杀至关重要的一个题材即使是内存以的题目。Android应用主要使用Java语言编写,因此这问题也同样会当Android开发被出现。本文不对准Java编程问题做探索,而是于以Android中,特别是使开发中之此类题材开展整理。

    由于笔者接触Android时间连无是颇丰富,因此若产生描述不当之处,欢迎指正。

亚、Android(Java)中泛的爱招惹内存泄漏的蹩脚代码

    Android主要行使在嵌入式设备中,而嵌入式设备由有些明显的极限制,通常还未会见产生甚高之配备,特别是内存是比有限的。如果我们编辑的代码当中发生极其多之对准内存使用不当的地方,难免会令我们的配备运行缓慢,甚至是死机。为了能够教Android应用程序安全都很快的周转,Android的每个应用程序都见面使一个专有的Dalvik虚拟机实例来运行,它是出于Zygote服务过程孵化出的,也就是说每个应用程序都是以属自己的过程被运行的。一方面,如果程序于运作过程被出现了内存泄漏的题目,仅仅会使自己的长河被kill掉,而不会见潜移默化其他进程(如果是system_process等体系经过有问题来说,则会挑起系统更开)。另一方面Android为歧种类的经过分配了不同之内存以上限,如果采取进程使的内存超过了之上限,则会为网即内存泄漏,从而被kill掉。Android为使进程分配的内存上限如下所示:

位置: /ANDROID_SOURCE/system/core/rootdir/init.rc 部分脚本

# Define the oom_adj values for the classes of processes that can be

# killed by the kernel.  These are used in ActivityManagerService.

    setprop ro.FOREGROUND_APP_ADJ 0

    setprop ro.VISIBLE_APP_ADJ 1

    setprop ro.SECONDARY_SERVER_ADJ 2

    setprop ro.BACKUP_APP_ADJ 2

    setprop ro.HOME_APP_ADJ 4

    setprop ro.HIDDEN_APP_MIN_ADJ 7

    setprop ro.CONTENT_PROVIDER_ADJ 14

    setprop ro.EMPTY_APP_ADJ 15

 

# Define the memory thresholds at which the above process classes will

# be killed.  These numbers are in pages (4k).

    setprop ro.FOREGROUND_APP_MEM 1536

    setprop ro.VISIBLE_APP_MEM 2048

    setprop ro.SECONDARY_SERVER_MEM 4096

    setprop ro.BACKUP_APP_MEM 4096

    setprop ro.HOME_APP_MEM 4096

    setprop ro.HIDDEN_APP_MEM 5120

    setprop ro.CONTENT_PROVIDER_MEM 5632

    setprop ro.EMPTY_APP_MEM 6144

 

# Write value must be consistent with the above properties.

# Note that the driver only supports 6 slots, so we have HOME_APP at the

# same memory level as services.

    write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15

 

    write /proc/sys/vm/overcommit_memory 1

    write /proc/sys/vm/min_free_order_shift 4

    write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144

 

    # Set init its forked children’s oom_adj.

    write /proc/1/oom_adj -16

 

    正因咱们的应用程序能够运用的内存有限,所以当编制代码的早晚需要特别注意内存以问题。如下是局部大面积的内存使用不当的景况。

 

(一) 查询数据库没有关闭游标

描述:

    程序中不时会面开展查询数据库的操作,但是时会发出使完毕Cursor后没有停歇的情形。如果我们的查询结果集于小,对内存的耗费不容易给发觉,只有在常时间大量操作的情下才见面复现内存问题,这样就算见面为以后的测试与问题排查带来困难和风险。

 

示范代码:

Cursor cursor = getContentResolver().query(uri …);

if (cursor.moveToNext()) {

    … … 

}

 

修正示例代码:

Cursor cursor = null;

try {

    cursor = getContentResolver().query(uri …);

    if (cursor != null && cursor.moveToNext()) {

        … … 

    }

} finally {

    if (cursor != null) {

        try { 

            cursor.close();

        } catch (Exception e) {

            //ignore this

        }

    }

 

(二) 构造Adapter时,没有行使缓存的 convertView

描述:

    以组织ListView的BaseAdapter为条例,在BaseAdapter中加强了方:

public View getView(int position, View convertView, ViewGroup parent)

来向ListView提供每一个item所欲的view对象。初始时ListView会从BaseAdapter中因当前之屏幕布局实例化一定数额之view对象,同时ListView会将这些view对象缓存起来。当发展滚动ListView时,原先在最上面的list item的view对象见面受回收,然后为用来组织新出现的最下的list item。这个布局过程尽管是出于getView()方法成功的,getView()的老二个亮参 View convertView就是于缓存起来的list item的view对象(初始化时缓存中从未view对象则convertView是null)。

    由这可以见见,如果我们无去采用convertView,而是每次都当getView()中还实例化一个View对象的讲话,即浪费资源也浪费时间,也会见叫内存占用越来越深。ListView回收list item的view对象的长河可以查:

android.widget.AbsListView.java –> void addScrapView(View scrap) 方法。

 

以身作则代码:

public View getView(int position, View convertView, ViewGroup parent) {

    View view = new Xxx(…);

    … …

    return view;

}

 

修正示例代码:

public View getView(int position, View convertView, ViewGroup parent) {

    View view = null;

    if (convertView != null) {

        view = convertView;

        populate(view, getItem(position));

        …

    } else {

        view = new Xxx(…);

        …

    }

    return view;

 

(三) Bitmap对象非以应用时调用recycle()释放内存

描述:

    有时我们见面手工的操作Bitmap对象,如果一个Bitmap对象比较占内存,当它们不在让运用的当儿,可以调用Bitmap.recycle()方法回收此目标的像素所占的内存,但马上不是要的,视情如果早晚。可以扣押一下代码中之诠释:

    /**

     * Free up the memory associated with this bitmap’s pixels, and mark the

     * bitmap as “dead”, meaning it will throw an exception if getPixels() or

     * setPixels() is called, and will draw nothing. This operation cannot be

     * reversed, so it should only be called if you are sure there are no

     * further uses for the bitmap. This is an advanced call, and normally need

     * not be called, since the normal GC process will free up this memory when

     * there are no more references to this bitmap.

     */

(四) 释放对象的援

描述:

    这种情况描述起来比麻烦,举两只例子进行求证。

示例A:

假设有如下操作

public class DemoActivity extends Activity {

    … …

    private Handler mHandler = …

    private Object obj;

    public void operation() {

     obj = initObj();

     …

     [Mark]

     mHandler.post(new Runnable() {

            public void run() {

             useObj(obj);

            }

     });

    }

}

    我们发一个分子变量 obj,在operation()中我们希望会将拍卖obj实例的操作post到某某线程的MessageQueue中。在以上的代码中,即便是mHandler所在的线程使用完毕了obj所引述的目标,但这目标仍不见面给垃圾回收掉,因为DemoActivity.obj还装有这个目标的援。所以一旦当DemoActivity中不再利用这目标了,可以当[Mark]的位置释放对象的援,而代码可以修改为:

… …

public void operation() {

    obj = initObj();

    …

    final Object o = obj;

    obj = null;

    mHandler.post(new Runnable() {

        public void run() {

            useObj(o);

        }

    }

}

… …

 

示例B:

    假设我们盼望于锁屏界面(LockScreen)中,监听系统中的对讲机服务以得到有音(如信号强度等),则可以在LockScreen中定义一个PhoneStateListener的靶子,同时将她注册及TelephonyManager服务被。对于LockScreen对象,当用出示锁屏界面的早晚便会见创造一个LockScreen对象,而当锁屏界面消失的时光LockScreen对象就见面让保释掉。

    但是一旦当放出LockScreen对象的时候忘记取消我们之前注册之PhoneStateListener对象,则会招LockScreen无法被垃圾回收。如果持续的若锁屏界面显示和消退,则最终见面由于大量之LockScreen对象没主意让回收而引起OutOfMemory,使得system_process进程挂掉。

    总之当一个生命周期较短的对象A,被一个生命周期较丰富之目标B保发那引述的状况下,在A的生命周期结束时,要以B中排除掉对A的援。

(五) 其他

    Android应用程序中最典型的需要留意放资源的图景是当Activity的生命周期中,在onPause()、onStop()、onDestroy()方法吃要相当的放资源的情状。由于是状万分基础,在这个不详细说明,具体可以查阅官方文档对Activity生命周期的牵线,以鲜明何时应该释放怎样资源。

转http://rayleeya.iteye.com/blog/727074

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图