Unity游戏引擎游戏开发时遇到unity 内存泄漏漏问题怎么办?

Unity5 引擎对游戏开发者意味着什么? - 开源中国社区
当前访客身份:游客 [
当前位置:
Unity5 引擎对游戏开发者意味着什么?
[核心提示] Unity 是全球顶级开发引擎之一,可以让开发者轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具。Unity5 可以使游戏开发者更加方便地设计出逼真画面与震撼音响,并拥有方便的跨平台开发能力。Camouflaj
是一家西雅图游戏公司,与 Unity 已经合作 5 年,开发了《Republique》共和国,Unity
使这家小团队游戏公司可以和大公司一样开发出酷炫的游戏。《Republique》是一款生存恐怖解谜游戏,源于英国作家乔治·奥威尔于 20 世纪
年代末所着的《1984》,这本政治讽喻小说刻画的是一个假想的极权主义社会,与英国作家赫胥黎著作的《美丽新世界》,以及俄国作家扎米亚京著作的《我
们》并称反乌托邦的三部代表作。游戏剧情讲述的就是年轻女主角身在此社会之中,给玩家打去一通绝望的电话,玩家帮助她逃离阴暗极权主义国家监管的故事。2013
年 9 月,《Republique》推出第一季,在最近的第四季度推出了 PC 和 Mac 版本,背后使用的就是
Unity5,以重构游戏。游戏最开始在手机平台推出,Camouflaj 希望这款游戏可以有更长的历史,在 PC、Mac
上都有展现,玩家遍布全球。从手机到 PC,Camouflaj 通过 Unity5 进行转换,Unity5 在光线、场景上的优化使整个游戏效果与真实场景更加贴近。使用Unity4与Unity5场景对比Unity
是全球顶级开发引擎之一,可以让开发者轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具。全球用户已经超
过 400 万,平均每两个手游开发者中有一个 Unity 开发者。中国用户超过百万,也是全球 Unity 用户最多的国家。在中国,Unity
与中国移动、中国联通、百度移动游戏、360 手机助手、91 安卓市场、腾讯应用宝、小米游戏等国内渠道平台合作。Unity
还拥有孵化项目:Unity 天地港首期三大工程包括孵化工程、成长加速工程和游戏评比工程。数十家国内外企业入驻。全新版本的
Unity 5 引擎已经能够支持包括 MAC OS X、安卓、IOS、Windows 等在内的二十一个平台发布。与上个版本相比,Unity 5
含有大量的图形改进和扩展的编辑器功能集。Unity 还发布了 Unity Cloud Build,使开发者通过云进行游戏和应用开发。Unity5 在功能上有几大优势:图形工具。增强图形功能,如基于物理的阴影、实时全局光照明和反射探头,创建震撼视觉体验。编辑器。对于苹果设备 64 位计算以及 Metal 技术的支持,拥有着全新的 Audio Mixer,对动画系统进行改善,升级物理系统。标准着色器。在任何光线环境下,跨移动、高端台式机和游戏机保持一致。在游戏中应用到超过 95% 的材料,例如金属、塑料、木材、陶瓷和布。使
开发,灯光的计算使场景布置快速烘培。人眼可以看到的所有材质,如木材、金属都可以设置,质感可以不断改变。游戏场景中大理石雕像可以展现出下雨的淋湿感
觉,光滑度可以轻松调出,真实度与美感兼具。改变材质也不需要美术重新画,纹理可以通过贴图改变。全新的反射探头,整个场景的反射更加真实。音效是游戏的
灵魂,Unity5 还可以把以前的音效,指定混音器,产生音效。21 种不同平台。跨越 21 种不同的平台,包括新的 WebGL,以及游戏主机、台式机、移动设备和 VR 设备。以
微软平台为例,从 Unity 进驻中国后,微软就与 Unity
合作。微软开发体验与平台合作事业部技术顾问总监赵立威认为:国内开发者目前拥有巨大的机遇,从设备市场、消费模式、App
以及游戏知识产权和宏观政策对创业都优势十足。UAP 是微软目前推崇的跨平台开发概念,从 5 寸手机平台到平板到
PC、Xbox,乃至更大显示器,通过一套开发框架发布到不同的 Windows 平台上。而 Unity 恰好支持 Windows
phone,Win8 等,包括 Xbox,与微软理念相同,游戏开发者可以不局限于 Windows
操作平台,实现不同操作系统和浏览器之间跨平台开发,Unity 工具对微软跨平台开发都有很大帮助。Unity Cloud Build。Unity 云构建功能为所有的 Unity 开发者带来了构建自动化,通过监控源码控制自动生成和分发构建版本,在检测到变化发生时,会为多个云计算平台生成项目,提高开发效率。题图:《Republique》游戏女主角稿源:
Unity3D 的详细介绍:
想通过手机客户端(支持 Android、iPhone 和 Windows Phone)访问开源中国:
旧一篇: 1年前
新一篇: 1年前
相关讨论话题
Unity5 引擎对游戏开发者意味着什么? 意味着免费,没有其他了,至少在盈利前都是免费的
2楼:zclouds
意味着折磨。出bug了你还真没法,因为没有源码!因为没有源码!
3楼:布洛克斯
暴雪用的是什么引擎
我觉得独立开发游戏,首先要解决的是模型的问题。引擎并非最关键的。
5楼:清靜無虞
对于程序员来说,美工永远是最难搞定的
6楼:会飞的螃蟹
引用来自“清靜無虞”的评论对于程序员来说,美工永远是最难搞定的精辟
7楼:撸脱臼
&&1984 &&好书
8楼:DF_XYZ
12:16 (非会员)
开发游戏最难的还是设计游戏本身
9楼:田晓阳 来自
引用来自“撸脱臼”的评论&&1984 &&好书真正的神作是&&美丽新世界&&
10楼:哆啦比猫 来自
引用来自“zclouds”的评论意味着折磨。出bug了你还真没法,因为没有源码!因为没有源码!好像可以讨要源码的
11楼:哆啦比猫 来自
12楼:zclouds
引用来自“zclouds”的评论意味着折磨。出bug了你还真没法,因为没有源码!因为没有源码!引用来自“哆啦比猫”的评论好像可以讨要源码的 求链接
13楼:哆啦比猫 来自
引用来自“zclouds”的评论意味着折磨。出bug了你还真没法,因为没有源码!因为没有源码!引用来自“哆啦比猫”的评论好像可以讨要源码的 引用来自“zclouds”的评论求链接又不是开源的哪来的链接“讨要”是要向客服要的
14楼:zclouds
引用来自“zclouds”的评论意味着折磨。出bug了你还真没法,因为没有源码!因为没有源码!引用来自“哆啦比猫”的评论好像可以讨要源码的 引用来自“zclouds”的评论求链接引用来自“哆啦比猫”的评论又不是开源的哪来的链接“讨要”是要向客服要的 有机会我试试。闻所未闻啊……
15楼:diguo2046 来自
u5刚出来,bug还是比较多。。还停留在4.5.5的飘过。
与内容无关的评论将被删除,严重者禁用帐号
本周热点资讯
本站最新资讯深入浅出再谈Unity内存泄漏
作者:Arthuryu,腾讯高级开发工程师著作权归作者所有。商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。本文通过对内存泄漏(what)及其危害性(why)的介绍,引出在Unity环境下定位和修复内存泄漏的方法和工具(how)。最后提出了一些避免泄漏的方法与建议。在之前推送的文章《内存是手游的硬伤——腾讯游戏谈Unity游戏Mono内存管理及泄漏问题》中,已经对腾讯游戏在Unity游戏开发过程中常见的Mono内存管理问题进行了介绍,收到了很多用户的反馈,希望能够更全面的介绍关于unity内存管理的问题。本期微信推送腾讯WeTest团队邀请到了公司中资深的测试专家Arthuryu,对Unity内存泄漏进行一个更加系统的介绍。相信各位程序猿们或多或少都会听到过内存泄漏这个名词,但是对于一些新手猿来说,或许不是很了解。内存泄漏?是内存漏出来了么?和霸气侧漏一样么?让我们先来看一下wikipedia的定义:看了一遍冗长的定义,或许各位猿们心中就是一个大写的“晕”字。让我们打一个通俗的比方来解释下这个定义。内存泄漏,可以通俗解释为“借银行钱不还”。在计算机的二进制世界里,操作系统就是银行;每一笔贷款,都是一次内存的申请;而你,就是一个应用程序。即你向银行贷款 = 应用程序向操作系统申请内存。当然,在计算机世界中,我们需要感谢操作系统,因为他是一个不收利息的银行,你借了多少内存,你就只需要还回多少内存。那么我们可以总结一下,内存泄漏的简单定义,就是申请了内存,却没有在该释放的时候释放。
北京时间8月27日,也就是在三星发布最新旗舰级Note7后的第二天,苹果公司提交给监管部门的文件显示库克在本周库克通过公...
&来源:轩科技
4、无线耳机苹果iPhone7/Plus将取消3.5mm耳机接口转而采用Lightning,此外...
&来源:极客派
随着历史的变迁,我国已发行了5套人民币。虽然有很多钱币退出了人们日常生活的舞台,但摇身一变却成了收藏界的明星。
&来源:中国经济网
距离华为新机5天,三星要发大招了。三星旗舰智能机S7 edge,是三星2016年推出的一款主打中高端市场的安卓机皇。
&来源:解毒互联网
[科技讯]8月28日消息,已证实!月球背面能够随意转换时空。近日,一个视频在网上爆火起来,视频的内容是一段访谈类节目...
&来源:科技讯
【黑客联盟日讯】现实世界当中的技术手段能够轻而易举地通过手机获取机主的一切信息吗?智能手机具备的最重...
&来源:黑客联盟
黑色沙滩之谜在冰岛最南端的维克小镇,有一片神秘的黑沙滩,经常有摄制组到这里取景拍摄科幻类型的影片。
&来源:一点资讯
三星S7 edge曲面屏确实很美,但是一不小心摔了,会心碎!华为P9徕卡双摄像头拍照确实不错,虽然一直说被自家发布的华为荣耀V8给坑了...
&来源:搞机女孩
2016年中国500强企业名单发布北京、山东、广东、江苏500强公司上榜企业最多!!!文:互联网热点主编王晶华北京时间8月27日...
&来源:互联网热点
你有没有想过:当你使用手机看书时就像上面操作一样,看书翻页变得如此简单?你以为这是虚幻?其实并不是...
&来源:科技数码堂
注:手机配置均为国际版,可能与国内配置略有所差别。10.乐视 乐Max2乐Max2是目前乐视配置最强大的Android手机...
&来源:科技浪尖
近日,一份行业报告显示:2015年直播行业市场规模约为150亿元,预计到2020年,整体规模还将继续上升至1060亿元,将会超过电影产业。
&来源:一点资讯
Ctrl+D&将本页面保存为书签,全面了解最新资讯,方便快捷。程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Android研究院之内存泄漏调试学习与总结(二十二)
Android研究院之内存泄漏调试学习与总结(二十二)
围观5673次
编辑日期: 字体:
开始学习啦,吼吼,小马很尽量写清楚自己想的与学习到的知识,希望大家不要嫌啰嗦,仔细看下小马描述与扩展的知识,一定能学到东西的!
好了,先简单说下,大家有或经常碰到OOM的问题,对吧?很多这样的问题只要一出现相信大家的想法跟小马的一样,就是自己的应用:优化、优化、再优化!而且如果出现类似于OOM这样级别的问题,根本就不好处理,LogCat日志中显示的信息仅仅是OOM,并不会给你提示如何解决的方法或思路,因为引起OOM的原因是你应用的问题,不是系统问题!应该想下,在优化之前找到需要优化的地方,再去做优化操作不是更直接吗?相信大多数朋友应该经常听过或使用Jnuit调试吧,好了,废话不多说,今天小马就跟大家一起来学习总结下OOM的调试方法,来找到需要优化的地方,要知道OOM也是可以一步步调试的:
首先,先一起来做些小小的知识铺垫:
Android(Java)中常见的容易引起内存泄漏的不良代码:
1. 查询数据库没有关闭游标
程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险示例代如下码:
1234567891011121314151617181920
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&&}&&}}
2. 构造Adapter时,没有使用缓存的 convertView ,这个问题小马上一篇:ListView加载数据原理及优化总结(二十一)中已经讲过了,大家可以回过头看下
3. Bitmap对象不在使用时调用recycle()没有及时释放
如果一个Bitmap对象比较占内存,当它不在被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存
4.没有及时释放对象的引用
简单举个例子:比如两个Activity之间传递的Context 或其它的自定义对象,使用完后必须立即释放 即:Activity =
Context = Object =可以的话在这释放对象之后通知系统来回收:System.gc();这样最好了!
Android主要应用在嵌入式设备当中,而嵌入式设备由于一些众所周知的条件限制,通常都不会有很高的配置,特别是内存是比较有限的。如果我们编写的代 码当中有太多的对内存使用不当的地方,难免会使得我们的设备运行缓慢,甚至是死机。为了能够使得Android应用程序安全且快速的运行,Android 的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程演变过来的,也就是说每个应用程序都是在属于自己的进程中运行的(问题一:这个地方小马怎么知道是在属于自己的进程中运行的?大家继续,答案小马会在下面详细介绍)。一方面,如果程序在运行过程中出现了内存泄漏的问题,仅仅会使得自己的进程被杀掉,而不会影响其他进程(如果是system_process 等系统进程出问题的话,则会引起系统重启)。另一方面Android为不同类型的进程分配了不同的内存使用上限,如果应用进程使用的内存超过了这个上限, 则会被系统视为内存泄漏,从而被杀掉
下面小马来解释下问题一:”每个应用程序都是在属于自己的进程中运行的”这句话,对于这句话,大家只记住一点:“当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。”~^_^
O_O !!!
同时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android会尝试停止一些进程从而释放足够的资源给其他新的进程使用, 也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。按照重要性从高到低一共有五个级别就是我们常说的:前台进程、可见进程、服务进程、后台进程、空进程(此处概念略,大家自己查)
还有个小扩展:当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。Android的UI是单线程(Single-threaded)的。为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。如果幕后的线程来执行UI对象,Android就会发出错误讯息 CalledFromWrongThreadException。以后遇到这样的异常抛出时就要知道怎么回事咯!
好了,铺垫知识就写这么多了,下面直接进入主题了:OOM调试
方式一:使用内存监测工具 DDMS –& Heap:(真机、模拟器均可使用)
1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图、Heap视图都是打开的,没打开的直接Window&ShowView&自己选;
2. 将手机通过USB链接至电脑,链接时需要确认手机是处于“USB调试”模式
3. 链接成功后,在DDMS的Devices视图中将会显示手机设备的序列号,以及设备中正在运行的部分进程信息;
4. 点击选中想要监测的进程,如果在进程列表中未出现你的进程的话随便选中一条让Device一排的工具处于可用状态,再点击下Update Heap让其自动找到我们跑的应用的进程,比如小马临时跑的两个应用进程如图;
5. 点击Heap视图中的“Cause GC”按钮;
6.点击Cause GC之后就可以看到我们应用的内存情况如下图:
a) 点击“Cause GC”按钮相当于向虚拟机请求了一次gc操作;
b) 当内存使用信息第一次显示以后,无须再不断的点击“Cause GC”,Heap视图界面会定时刷新,在对应用的不断的操作过程中就可以看到内存使用的变化;
c) 内存使用信息的各项参数根据名称即可知道其意思,不知道具体意思的朋友自行用工具(有道、词霸查去)
知道工具使用了,那么如何才能知道我们的程序是否有内存泄漏的可能性呢。这里需要注意一个值:Heap视图中部有一个Type叫做data object,即数据对象,也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,如果大家想要看“Total Size”是分配的具体信息可以点击“data object这一行来查看详细信息,如下图”(大家看不清楚的点击看大图)
一般情况下,在data object行的“Total Size”这个值的大小决定了是否会有内存泄漏。可以这样判断:
a) 不断的操作当前应用,同时注意观察data object的Total Size值;
b) 正常情况下Total Size值都会稳定在一个有限的范围内,也就是说由于程序中的的代码良好,没有造成对象不被垃圾回收的情况,所以说虽然我们不断的操作会不断的生成很多对 象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会会落到一个稳定的水平;
c) 反之如果代码中存在没有释放对象引用的情况,则data object的Total Size值在每次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大,
直到到达一个上限后导致进程被杀掉。
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 96,44
# Set init its forked children’s oom_adj.
write /proc/1/oom_adj -16
d) 此处以com.xiaoma.www进程为例,在我的测试环境中com.xiaoma.www进程所占用的内存的data object的Total Size正常情况下稳定在0.8~1.0M之间,而当其值超过3~5M每次启动应用该值不稳定的时候进程就会被系统杀掉啦!
内存监测工具 DDMS –& Heap
使用内存分析工具 MAT(Memory Analyzer Tool)
(一) 生成.hprof文件 (生成很简单,直接点击Device 工具栏中的 Dump HPROF file即可生成)
(二) 使用MAT导入.hprof文件
(三) 使用MAT的视图工具分析内存
总之,使用DDMS的Heap视图工具可以很方便的确认我们的程序是否存在内存泄漏的可能性。这个地方顺带着也简单的说一下,如果大家想要跟踪更详细的内存是怎样分配的话,可以学着使用下Windows&ShowView&Allocation Tracker工具来定位你的内存什么时候被什么东西占用了,是bundlea或HashMap或ArrayList焦点或是其它的什么占用了这些都可以在这个插件中查看到的,简单的使用方法就是:选中Device进程列表中的某一个进程,让Allocation Tracker里面的跟踪工具处于可用状态,点击Stop Tracking来跟踪程序,过一定时间后,点击Get Allocations来获取内存分配的消息就可以查看更为详细的内存分配情况了,如下图:
Allocation Tracker这个小工具比较简单, 小马在这个地方不一一说明了,想学的朋友们自己点击看看就会知道里面的参数是什么意思了…..^_^……..最后,还是一样,小马在内存管理方面还要学的东西很多,如果文章中小马有讲的不清楚或不足之处,大家留言批评并提出更好的建议,小马一定及时改进,在此先谢谢大家啦,吼吼学习学习!大家加油,一起进步!!!
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:小马果
【誓言、会老】…【承诺、会变】…【目标、遥远】…【选择、不后悔】…【对自己要狠】…所有动力,源自兴趣,爱编程,更过编程的过程.....
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!请教内存泄漏问题,大侠指点!
[问题点数:100分,结帖人cdpdaopin]
请教内存泄漏问题,大侠指点!
[问题点数:100分,结帖人cdpdaopin]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
本帖子已过去太久远了,不再提供回复功能。Java(70)
程序中的“内存泄漏”问题
大多数程序员都知道,使用Java编程语言的一大好处就是,不必再担心内存的分配和释放问题。您只须创建对象,当应用程序不再需要这些对象时,Java&会通过一种称为“垃圾回收”的机制将这些对象的内存释放掉。他们认为Java不存在内存泄漏问题,或者认为即使有内存泄漏也不是程序的责任,而是垃圾回收器(GC)或Java虚拟机(JVM)的问题。但事实真的是这样吗?Java真的已经解决了困扰其他编程语言的内存泄露问题了吗?
一、Java的内存管理机制
在进一步讨论之前,我们先了解一下Java的内存管理机制。Java的内存管理就是对象的分配和释放问题。在Java中,程序员需要通过关键字new为每个对象申请内存空间&(基本类型除外),所有的对象都在堆&(Heap)中分配空间。在Java中,内存的分配是由程序完成的,而内存的释放是则是由垃圾回收器决定和执行的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的负担,这也是Java程序运行速度较慢的原因之一。因为,垃圾回收器为了能够正确回收对象,必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等。监视对象状态是为了准确、及时地释放对象,而释放对象的基本原则就是该对象是否仍被引用。
垃圾收集器的工作是发现应用程序不再需要的对象,并在这些对象不再被访问或引用时将它们删除。垃圾收集器从根节点(在&Java&应用程序的整个生存周期内始终存在的那些类)开始,遍历所有仍被引用的节点,进行垃圾回收。任何对象只要不再被引用,就符合垃圾回收的条件。垃圾回收器回收这些对象后,它们所占用的内存资源也就被返回给了Java虚拟机。
Java使用有向图的方式进行内存管理,可以消除循环引用的问题,例如有三个对象,相互引用,只要它们和根线程不可达,那么垃圾回收器也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度较低(很难处理循环引用的问题),但执行效率却很高。
为了更好理解地垃圾回收器的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用对象指向被引对象。每个线程可以作为一个图的起始顶点,例如大多程序从main线程开始执行,那么该图就是以main线程为顶点的一个有向图。在这个有向图中,根顶点可达的对象都是有效对象,如果某个对象不可达,那么垃圾回收器会认为这个对象不再被引用,可以被回收。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。
Java中的内存泄露
在C++&程序中,内存泄漏是指应用程序为某些对象被分配了内存空间,然后却因为某些原因不可达,以至于被这些对象使用的内存无法被释放并返还给操作系统,这些内存将永远收不回来。
令人欣慰的是,这种内存泄露问题在Java程序中并不存在。在Java中,对象使用的内存都由垃圾回收器负责回收的,而Java虚拟机并不存在任何被证实的内存泄漏问题。实践证明,垃圾收集器一般能够精确地判断哪些对象可被收集,回收它们占用的内存空间并返还给Java&虚拟机。
对于Java来说,内存泄漏是指在程序中存在一些实际上并不需要的对象引用。这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。一个典型的例子是向一个集合中加入一些对象以便以后使用它们,但是却没有在使用完后从集合中删除对这些对象的引用。因为集合可以无限制地扩大,并且从来不会变小,所以当向集合中加入了太多的对象(或者是有很多的对象被集合中的元素所引用)时,就会因为堆空间被填满而导致内存耗尽。垃圾收集器并不会把这些您认为已经用完的对象当作垃圾进行回收,因为对于垃圾收集器来说,应用程序仍然可以通过这个集合在任何时候访问这些对象。
1、静态集合类引起内存泄露:
在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null。
2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。
通过以上分析,可以知道在Java中也有内存泄漏,但范围比C++要小一些。因为Java从语言上保证,任何对象都是可达的,都由垃圾回收器进行内存的回收管理。
随着越来越多的服务器程序、嵌入式系统及游戏平台采用Java技术,出现了较多内存有限、需要长期运行Java应用。内存泄露问题也就变得十分关键,即使每次少量内存泄漏,长期运行之后,系统也有面临内存溢出的危险。
问题及解决方法
我们知道了在Java中确实会存在内存泄漏,那么就让我们看一看几种典型的泄漏,并试图找出他们的解决方法。
3.1&全局集合
在大型应用程序中存在各种各样的全局数据储存库是很普遍的,比如一个Session Table。在这些情况下,必须注意管理储存库的大小。必须使用某种机制从储存库中移除不再需要的数据。
通常有很多不同的解决形式,其中最常用的一种是周期运行的清除作业。这个作业会验证仓库中的数据然后清除一切不需要的数据。
另一种管理储存库的方法是使用反向链接(Referrer)计数。然后集合负责统计集合中每个元素反向链接的数目,当反向链接数目为零时,该元素就可以从集合中移除了。&
&&&&缓存一种用来快速查找已经执行过的操作结果的。因此,如果一个操作执行需要比较多的资源并会多次被使用,通常做法是把常用的输入数据的操作结果进行缓存,以便在下次调用该操作时使用缓存中的数据。缓存通常都是以动态方式实现的,如果缓存设置不正确而大量使用缓存的话,则会出现内存溢出的后果,因此需要将所使用的内存容量与检索数据的速度加以平衡。
常用的解决途径是使用软引用或弱引用类将对象放入缓存。这个方法可以保证当虚拟机用完内存或者需要更多堆的时候,可以释放这些对象的引用。
3.3&类装载器
Java类装载器的使用为内存泄漏提供了许多可乘之机。一般来说类装载器都具有复杂结构,因为类装载器不仅仅是只与“常规”的对象引用有关,同时也和对象内部的引用有关。比如数据变量,方法和各种类。这意味着只要存在对数据变量,方法,各种类和对象的引用,那么类装载器将驻留在Java虚拟机中。既然类装载器可以同很多的类关联,同时也可能和静态数据变量关联,那么相当多的内存就可能发生泄漏。
3.4&物理连接
一些物理连接,比如连接和网络连接,除非其显式的关闭了连接,否则是不会自动被GC&回收的。Java数据库连接一般用DataSource.getConnection()来创建,当不再使用时必须用Close()方法来释放。对于ResultSet&和Statement&对象可以不进行显式回收,但Connection&一定要显式回收,,因为这些连接是独立于Java虚拟机的,在任何时候都无法自动回收,而Connection一旦回收,ResultSet&和Statement&对象就会立即变为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭ResultSet和Statement&对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement&对象无法释放,从而引起内存泄漏。
3.5&内部模块和外部模块等的引用
内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。对于程序员而言,自己的程序很清楚,如果发现内存泄漏,自己对这些对象的引用可以很快定位并解决。但是在大型应用软件的开发中,整个系统并非一个人实现,个人担当的可能只是系统的某一机能或某机能的一个模块。所以程序员要小心外部模块不经意的引用,例如程序员A&负责A&模块,调用了B模块的一个方法如:public void registerMsg(Object b);&这种调用就要非常小心了,传入了一个对象,很可能模块B就保持了对该对象的引用,这时候就需要注意模块B是否需要提供相应的去除引用的操作。
四、如何找出内存泄漏
查找内存泄漏一般有两种方法:一是安排有经验的编程人员对代码进行走查和分析,找出内存泄漏发生的位置;二是使用专门的内存泄漏测试工具进行测试。
第一种方法,在代码走查工作中,可以安排对系统业务和开发语言较熟悉的开发人员对应用的代码进行了交叉走查,尽量找出代码中存在的数据库连接声明和结果集未关闭、代码冗余等问题代码。
第二种方法就是使用专门的内存泄漏工具进行测试。市场上已有专业检查Java内存泄漏的工具,它们的基本工作原理大同小异,都是通过监测Java程序运行时,所有对象的申请、释放等动作,将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。常用的工具有Optimizeit Profiler,JProbe Profiler,JinSight以及Rational公司的Purify等。
五、Java中的几种引用方式
&&&&Java中有几种不同的引用方式,它们分别是:强引用、软引用、弱引用和虚引用。下面,我们首先详细地了解下这几种引用方式的意义。
在此之前我们介绍的内容中所使用的引用OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
SoftReference&类的一个典型用途就是用于内存敏感的高速缓存。SoftReference&的原理是:在保持对对象的引用时保证在&JVM&报告内存不足情况之前将清除所有的软引用。关键之处在于,垃圾收集器在运行时可能会(也可能不会)释放软可及对象。对象是否被释放取决于垃圾收集器的&以及垃圾收集器运行时可用的内存数量。
WeakReference&类的一个典型用途就是规范化映射(canonicalized&mapping)。另外,对于那些生存期相对较长而且重新创建的开销也不高的对象来说,弱引用也比较有用。关键之处在于,垃圾收集器运行时如果碰到了弱可及对象,将释放&WeakReference&引用的对象。然而,请注意,垃圾收集器可能要运行多次才能找到并释放弱可及对象。
PhantomReference&类只能用于跟踪对被引用对象即将进行的收集。同样,它还能用于执行&pre-mortem&清除操作。PhantomReference&必须与&ReferenceQueue&类一起使用。需要&ReferenceQueue&是因为它能够充当通知机制。当垃圾收集器确定了某个对象是虚可及对象时,PhantomReference&对象就被放在它的&ReferenceQueue&上。将&PhantomReference&对象放在&ReferenceQueue&上也就是一个通知,表明&PhantomReference&对象引用的对象已经结束,可供收集了。这使您能够刚好在对象占用的内存被回收之前采取行动。Reference与ReferenceQueue的配合使用。
GC、与的交互
GC无法删除存在强引用的对象的内存。
GC发现一个只有软引用的对象内存,那么:
①&SoftReference对象的referent&域被设置为null,从而使该对象不再引用heap对象。
②&SoftReference引用过的heap对象被声明为finalizable。
③&当&heap&对象的&finalize()&方法被运行而且该对象占用的内存被释放,SoftReference&对象就被添加到它的&ReferenceQueue(如果后者存在的话)。
GC发现一个只有弱引用的对象内存,那么:
①&WeakReference对象的referent域被设置为null,从而使该对象不再引用heap对象。
②&WeakReference引用过的heap对象被声明为finalizable。
③&当heap对象的finalize()方法被运行而且该对象占用的内存被释放时,WeakReference对象就被添加到它的ReferenceQueue(如果后者存在的话)。
GC发现一个只有虚引用的对象内存,那么:
①&PhantomReference引用过的heap对象被声明为finalizable。
②&PhantomReference在堆对象被释放之前就被添加到它的ReferenceQueue。
值得注意的地方有以下几点:
1、在一般情况下不会发现软引用的内存对象,只有在内存明显不足的时候才会发现并释放软引用对象的内存。
2、对弱引用的发现和释放也不是立即的,有时需要重复几次,才会发现并释放弱引用的内存对象。
3、软引用和弱引用在添加到的时候,其指向真实内存的引用已经被置为空了,相关的内存也已经被释放掉了。而虚引用在添加到的时候,内存还没有释放,仍然可以对其进行访问。
&&&&代码示例
通过以上的介绍,相信您对的引用机制以及几种引用方式的异同已经有了一定了解。光是概念,可能过于抽象,下面我们通过一个例子来演示如何在代码中使用机制。
在以上代码中,注意⑤⑥两处地方。假如“”对象没有被回收将返回“”字符串对象,返回;而加入“”对象已经被回收了,那么返回,返回对象,但是此对象中已经没有对象的引用了PhantomReference则与WeakReference、SoftReference不同)。
&&&&引用机制与复杂数据结构的联合应用
&&&&了解了机制、引用机制,并配合上,我们就可以实现一些防止内存溢出的复杂数据类型。
例如,具有构建系统的特质,因此我们可以结合哈希表实现一个简单的缓存系统。这样既能保证能够尽可能多的缓存信息,又可以保证虚拟机不会因为内存泄露而抛出。这种缓存机制特别适合于内存对象生命周期长,且生成内存对象的耗时比较长的情况,例如缓存列表封面图片等。对于一些生命周期较长,但是生成内存对象开销不大的情况,使用能够达到更好的内存管理的效果。
附的源码一份,相信看过之后,大家会对机制的应用有更深入的理解。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:44824次
积分:2034
积分:2034
排名:第13820名
原创:158篇
转载:28篇
阅读:2923
(2)(26)(19)(35)(20)(1)(3)(14)(1)(2)(2)(1)(10)(20)(5)(19)(10)

我要回帖

更多关于 unity 检测内存泄漏 的文章

 

随机推荐