android system.out.println中文乱码 会导致内存溢出吗

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Android避免内存溢出(Out of Memory)方法汇总
转载 & & 作者:ZHU_文涛
这篇文章主要为大家详细介绍了Android避免内存溢出Out of Memory方法汇总,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
避免内存溢出的方法,主要是对以下三个方面对程序进行优化
在处理内存引用之前,我们先来复习下什么是强引用、软引用、弱引用、虚引用
强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
软引用:如果一个对象只具有软引用,但内存空间足够时,垃圾回收器就不会回收它;直到虚拟机报告内存不够时才会回收, 只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
虚引用:虚引用可以理解为虚设的引用,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。 虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。 程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。 如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
1、释放强引用
一般我们在声明对象变量时,使用完后就不管了,认为垃圾回收器会帮助我们回收这些对象所指向的内存空间,实际上如果这个对象的内存空间还处在被引用状态的话,垃圾回收器是永远不会回收它的内存空间的,只有当这个内存空间不被任何对象引用的时候,垃圾回收器才会去回收。
所以我们在使用完对象后,可以把对象置为空,这样我的垃圾回收器gc就会在合适的时候释放掉为该对象分配的内存空间
Object obj = new Object();
当然,在置为空前要确认是否不再需要使用该对象了,如果需要随时使用这个对象,则不能这么做
2、使用软引用
在jvm报告内存不足之前会清除所有的软引用,这样的话gc就可以收集到很多软引用释放出来的内存空间,从而解决内存吃紧的问题,避免内存溢出,什么时候被回收取决于gc的算法和gc运行时可用的内存大小。
我们可以用SoftReference来封装强引用的对象
String str = "zhuwentao";
SoftReference&String& strSoft = new SoftReference&String&(str);
// 使用软引用封装强引用
3、使用弱引用
gc收集弱引用对象的执行过程和软引用一样,只是gc不会根据内存情况来决定是否回收弱引用的对象。
String str = "zhuwentao";
WeakReference&String& strWeak = new WeakReference&String&(str);
// 使用弱引用封装强强引用
如果你希望能够随时取得某个对象的信息,但又不希望影响该对象的垃圾回收,则应该使用WeakReference来记住该对象,而不是使用一般的Reference。
大部分的OOM都是发生在图片加载上的,当我们加载大图时,需要特别注意避免OOM的发生。
处理大图片时,不管你的手机内存有多大,如果不对图片进行处理,都有可能会发生内存溢出问题。
因为Android系统会为每一个应用分配一定大小的内存,并不会把整个系统内存全部分给应用,所以不管你手机内存多大,对每个App来说,它能使用的内存都是有限的。
这和PC端是有很大的不同,PC端如果内存不够了还可以请求使用虚拟内存,而Android系统可没这个机制。
1、在内存中压缩图片
装载大图片时需要对图片进行压缩,使用等比例压缩的方法直接在内存中处理图片
Options options = new BitmapFactory.Options();
options.inSampleSize = 5; // 原图的五分之一,设置为2则为二分之一
BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);
这样做要注意的是,图片质量会变差,inSampleSize设置的值越大,图片质量就越差,不同的手机厂商缩放的比例可能不同。
2、使用完图片后回收图片所占内存
由于Android外层是使用java而底层使用的是c语言在里层为图片对象分配的内存空间。
所以我们的外部虽然看起来释放了,但里层却并不一定完全释放了,我们使用完图片后最好再释放掉里层的内存空间。
if (!bitmapObject.isRecyled()) {
// Bitmap对象没有被回收
bitmapObject.recycle();
System.gc();
// 提醒系统及时回收
3、降低要显示的图片色彩质量
Android中Bitmap有四种图片色彩模式:
ALPHA_8:每个像素需要占用内存中的1byte
RGB_565:每个像素需要占用内存中的2byte
ARGB_4444:每个像素需要占用内存中的2byte
ARGB_8888:每个像素需要占用内存中的4byte
我们创建Bitmap时,默认的色彩模式是ARGB_8888的,这种色彩模式是质量最高的,当然这样的模式占用的内存也最大。
而ARGB_4444每个像素只占用2byte,所以使用ARGB_4444的模式也能降低图片占用的内存大小。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);
其实大多数图片设置成ARGB_4444模式后,在显示上是看不出与ARGB_8888模式有什么差别的,只是在具有渐变色效果的图片时,可能会让渐变色呈现色彩条样的效果。
这种降低色彩质量的方法对内存的降低效果不如方法1明显。
4、查询图片信息时不把图片加载到内存中
有时候我们取得一张图片,也许只是为了获得这个图片的一些信息,比如图片的width、height等信息,不需要显示到界面上,这个时候我们可以不把图片加载到内存中。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds =
// 不把图片加载到内存中
Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);
inJustDecodeBounds属性,如果值为true,那么将不返回实际的Bitmap对象,也不给其分配内存空间,但允许我们查询图片宽、高、大小等基本信息。
(获取原始宽高:options.outWidth,options.outHeight)
VMRuntime是Android SDK中提供的一个类。
只在Android2.3以前有用,2.3以后的SDK就不支持了,所以这个VMRuntime并不通用。
这里简单介绍下就好了。
1、优化Dalvik虚拟机的堆内存分配
VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。
private final static float TARGET_HEAP_UTILIZATION = 0.75f;
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
2、自定义堆内存大小
强制定义Android给当前App分配的内存大小,使用VMRuntime设置应用最小堆内存。
// 设置最小heap内存为 6MB 大小
private final static int HEAP_SIZE = 6 * 1024 * 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(HEAP_SIZE);
让Dalvik虚拟机为App分配更大的内存,该方法能为我们的App争取到更多内存空间,从而缓解内存不足的压力
可以在程序中使用ActivityManager.getMemoryClass()方法来获取App内存正常使用情况下的大小,通过ActivityManager.getLargeMemoryClass()可获得开启largeHeap时最大的内存大小
1、使用方法
该方法使用非常简单,只要在AndroidManifest.xml文件中的&application&节点属性中加上”android:largeHeap="true"“
&application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:largeHeap="true"
Dalvik为我们App增加的内存很可能是通过杀死其它后台进程获取的内存,这样的做法对于一个开发者来说并不道义
我们不应该把解决OOM的问题寄托在争取最大的内存上,应该通过合理的代码编写来尽可能的规避OOM问题。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具彻底解决Android因加载多个大图引起的OutOfMemoryError,内存溢出的问题 - 海王 - 博客园
随笔 - 548
最近因为项目里需求是选择或者拍摄多张照片后,提供滑动预览和上传,很多照片是好几MB一张,因为目前的Android系统对运行的程序都有一定的内存限制,一般是16MB或24MB(视平台而定),不做处理直接加载的话必然会报OOM (Out Of Memmory)。网上有很多解决android加载bitmap内存溢出的方法,我总结了一个通用的方法,下面是我从的开发案例抽取出来的代码:
我在项目中建了个Util.java工具类,里面写了个方法,根据图片的路径返回一个字节流数组对象:
public&static&byte[]&decodeBitmap(String&path)&{&&
&&&&&&&&BitmapFactory.Options&opts&=&new&BitmapFactory.Options();&&
&&&&&&&&opts.inJustDecodeBounds&=&true;&&
&&&&&&&&BitmapFactory.decodeFile(path,&opts);&&
&&&&&&&&opts.inSampleSize&=&computeSampleSize(opts,&-1,&1024&*&800);&&
&&&&&&&&opts.inJustDecodeBounds&=&false;&&
&&&&&&&&opts.inPurgeable&=&true;&&
&&&&&&&&opts.inInputShareable&=&true;&&
&&&&&&&&opts.inDither&=&false;&&
&&&&&&&&opts.inPurgeable&=&true;&&
&&&&&&&&opts.inTempStorage&=&new&byte[16&*&1024];&&
&&&&&&&&FileInputStream&is&=&null;&&
&&&&&&&&Bitmap&bmp&=&null;&&
&&&&&&&&ByteArrayOutputStream&baos&=&null;&&
&&&&&&&&try&{&&
&&&&&&&&&&&&is&=&new&FileInputStream(path);&&
&&&&&&&&&&&&bmp&=&BitmapFactory.decodeFileDescriptor(is.getFD(),&null,&opts);&&
&&&&&&&&&&&&double&scale&=&getScaling(opts.outWidth&*&opts.outHeight,&&
&&&&&&&&&&&&&&&&&&&&1024&*&600);&&
&&&&&&&&&&&&Bitmap&bmp2&=&Bitmap.createScaledBitmap(bmp,&&
&&&&&&&&&&&&&&&&&&&&(int)&(opts.outWidth&*&scale),&&
&&&&&&&&&&&&&&&&&&&&(int)&(opts.outHeight&*&scale),&true);&&
&&&&&&&&&&&&bmp.recycle();&&
&&&&&&&&&&&&baos&=&new&ByteArrayOutputStream();&&
&&&&&&&&&&&&bmp2.compress(Bitmap.CompressFormat.JPEG,&100,&baos);&&
&&&&&&&&&&&&bmp2.recycle();&&
&&&&&&&&&&&&return&baos.toByteArray();&&
&&&&&&&&}&catch&(FileNotFoundException&e)&{&&
&&&&&&&&&&&&e.printStackTrace();&&
&&&&&&&&}&catch&(IOException&e)&{&&
&&&&&&&&&&&&e.printStackTrace();&&
&&&&&&&&}&finally&{&&
&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&is.close();&&
&&&&&&&&&&&&&&&&baos.close();&&
&&&&&&&&&&&&}&catch&(IOException&e)&{&&
&&&&&&&&&&&&&&&&e.printStackTrace();&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&System.gc();&&
&&&&&&&&}&&
&&&&&&&&return&baos.toByteArray();&&
&&&&private&static&double&getScaling(int&src,&int&des)&{&&
&&&&&&&&double&scale&=&Math.sqrt((double)&des&/&(double)&src);&&
&&&&&&&&return&&&
&&&&public&static&int&computeSampleSize(BitmapFactory.Options&options,&&
&&&&&&&&&&&&int&minSideLength,&int&maxNumOfPixels)&{&&
&&&&&&&&int&initialSize&=&computeInitialSampleSize(options,&minSideLength,&&
&&&&&&&&&&&&&&&&maxNumOfPixels);&&
&&&&&&&&int&roundedS&&
&&&&&&&&if&(initialSize&&=&8)&{&&
&&&&&&&&&&&&roundedSize&=&1;&&
&&&&&&&&&&&&while&(roundedSize&&&initialSize)&{&&
&&&&&&&&&&&&&&&&roundedSize&&&=&1;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&roundedSize&=&(initialSize&+&7)&/&8&*&8;&&
&&&&&&&&}&&
&&&&&&&&return&roundedS&&
&&&&private&static&int&computeInitialSampleSize(BitmapFactory.Options&options,&&
&&&&&&&&&&&&int&minSideLength,&int&maxNumOfPixels)&{&&
&&&&&&&&double&w&=&options.outW&&
&&&&&&&&double&h&=&options.outH&&
&&&&&&&&int&lowerBound&=&(maxNumOfPixels&==&-1)&?&1&:&(int)&Math.ceil(Math&&
&&&&&&&&&&&&&&&&.sqrt(w&*&h&/&maxNumOfPixels));&&
&&&&&&&&int&upperBound&=&(minSideLength&==&-1)&?&128&:&(int)&Math.min(&&
&&&&&&&&&&&&&&&&Math.floor(w&/&minSideLength),&Math.floor(h&/&minSideLength));&&
&&&&&&&&if&(upperBound&&&lowerBound)&{&&
&&&&&&&&&&&&return&lowerB&&
&&&&&&&&}&&
&&&&&&&&if&((maxNumOfPixels&==&-1)&&&&(minSideLength&==&-1))&{&&
&&&&&&&&&&&&return&1;&&
&&&&&&&&}&else&if&(minSideLength&==&-1)&{&&
&&&&&&&&&&&&return&lowerB&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&return&upperB&&
&&&&&&&&}&&
然后在我需要加载图片BitMap的地方来调用Util.decodeBitmap():
Bitmap&bitmap&=&BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath),&0,&Util.decodeBitmap(imagePath).length);&&
&&&&&&&&&&&&&&&&imageCache.put(imagePath,&new&SoftReference&Bitmap&(bitmap));&&
上面这两行是我的AsyncImageLoaderByPath类中的代码,用来加载SD卡里面的图片,该类完整代码是:
package&com.pioneer.travel.&&
import&java.io.IOE&&
import&java.io.InputS&&
import&java.lang.ref.SoftR&&
import&java.net.MalformedURLE&&
import&java.net.URL;&&
import&java.util.HashM&&
import&android.content.C&&
import&android.graphics.B&&
import&android.graphics.BitmapF&&
import&android.graphics.BitmapFactory.O&&
import&android.graphics.drawable.D&&
import&android.os.H&&
import&android.os.M&&
import&android.provider.MediaS&&
import&android.util.L&&
import&android.widget.ImageV&&
public&class&AsyncImageLoaderByPath&{&&
&&&&private&HashMap&String,&SoftReference&Bitmap&&&imageC&&
&&&&private&Context&&&
&&&&public&AsyncImageLoaderByPath(Context&context)&{&&
&&&&&&&&this.imageCache&=&new&HashMap&String,&SoftReference&Bitmap&&();&&
&&&&&&&&this.context&=&&&
&&&&public&Bitmap&loadBitmapByPath(final&String&imagePath,&final&ImageView&imageView,&final&ImageCallback&imageCallback){&&
&&&&&&&&if&(imageCache.containsKey(imagePath))&{&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&SoftReference&Bitmap&&softReference&=&imageCache.get(imagePath);&&
&&&&&&&&&&&&Bitmap&bitmap&=&softReference.get();&&
&&&&&&&&&&&&if&(bitmap&!=&null)&{&&
&&&&&&&&&&&&&&&&return&&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&final&Handler&handler&=&new&Handler()&{&&
&&&&&&&&&&&&public&void&handleMessage(Message&message)&{&&
&&&&&&&&&&&&&&&&imageCallback.imageLoaded((Bitmap)&message.obj,&imageView,&imagePath);&&
&&&&&&&&&&&&}&&
&&&&&&&&};&&
&&&&&&&&&&
&&&&&&&&new&Thread()&{&&
&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&&&&&Bitmap&bitmap&=&BitmapFactory.decodeByteArray(Util.decodeBitmap(imagePath),&0,&Util.decodeBitmap(imagePath).length);&&
&&&&&&&&&&&&&&&&imageCache.put(imagePath,&new&SoftReference&Bitmap&(bitmap));&&
&&&&&&&&&&&&&&&&Message&message&=&handler.obtainMessage(0,&bitmap);&&
&&&&&&&&&&&&&&&&handler.sendMessage(message);&&
&&&&&&&&&&&&}&&
&&&&&&&&}.start();&&
&&&&&&&&return&null;&&
&&&&public&interface&ImageCallback&{&&
&&&&&&&&public&void&imageLoaded(Bitmap&imageBitmap,ImageView&imageView,&String&imagePath);&&
通过这个实例,我验证了一下,一次性获取20张5MB的照片,都可以加载的很流畅,完全没有再出现报OOM的错误了
以下是运行效果
SD卡中的图片:
阅读(...) 评论()
Copyright & 海王
Powered by:
模板提供:博客分类:
今天遇到个小问题,之前都没注意,现在mark一下。
java中一般打印方法为System.out.println("");如果程序没问题,要打印的内容会在控制台显示。
但在Android平台,调用System.out.println("")函数,即使程序正确,也不会在控制台显示。不过可以在LogCat中查看。Android自身提供的打印方法是Log.v,引入android.util.Log 即可使用。查看打印的字符也不在console面板,而在Log面板上,可以选择ide右上角debug模式,查看Log面板。
浏览 17959
浏览: 122625 次
来自: 浙江
yaqing503 写道您好!我按照您给的步骤完成了环境的配置 ...
yaqing503 写道您好!我按照您给的步骤完成了环境的配置 ...
http://nobb.iteye.com/adminhttp ...
sjsmilelife 写道imread读取不了sdcard
imread读取不了sdcard 的图片,已经加权限了还是不行 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'1. 当项目中包含大量图片,或者图片过大,可能会oom
等比例缩小图片
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
对图片采用软引用,及时地进行recyle()操作
SoftReference&Bitmap&
bitmap = new SoftReference&Bitmap&(pBitmap);
if(bitmap != null){
if(bitmap.get() != null && !bitmap.get().isRecycled()){
bitmap.get().recycle();
对复杂的listview进行合理设计与编码:
1. 注意重用Adapter里面的 convertView
以及holder机制的运用
----- 参考资料api demo list 14. Efficient Adapter
2.上述方法尝试还未成功,可用 lazy loading data
----- 参考资料:api demo
方法4 : 单个页面,横竖屏切换N次后 OOM
1. 看看页面布局当中有没有大的图片,比如背景图之类的。去除xml中相关设置,改在程序中设置背景图(放在onCreate()方法中):
2. 跟上面方法相似,直接把xml配置文件加载成view 再放到一个容器里,然后直接调用 this.setContentView(View view)方法,避免xml的重复加载
方法5 : 在页面切换时尽可能少地重复使用一些代码,比如:重复调用数据库,反复使用某些对象等等......
方法6 :Android堆内存也可自己定义大小和优化Dalvik虚拟机的堆内存分配
注意:若使用这种方法:project build target 只能选择 &= 2.2 版本,否则编译将通不过。 所以不建议用这种方式
2、Android 内存溢出解决方案(OOM) 整理总结
1:软引用(SoftReference)、虚引用(PhantomRefrence)、弱引用(WeakReference),这三个类是对heap中java对象的应用,
通过这个三个类可以和gc做简单的交互,除了这三个以外还有一个是最常用的强引用
1.1:强引用,例如下面代码:
Object o = new Object();
Object o1=o;
上面代码中:
第一句是在heap堆中创建新的Object对象通过o引用这个对象,第二句是通过o建立o1到new Object()这个heap堆中的对象的引用,
这两个引用都是强引用.只要存在对heap中对象的引用,gc就不会收集该对象.如果通过如下代码:
heap中对象有强可及对象、软可及对象、弱可及对象、虚可及对象和不可到达对象。
应用的强弱顺序是强、软、弱、和虚。对于对象是属于哪种可及的对象,由他的最强的引用决定。如下:
String abc = new String("abc");
SoftReference&String& abcSoftRef = new SoftReference&String&(abc);
WeakReference&String& abcWeakRef = new WeakReference&String&(abc); //3
abcSoftRef.clear();//5
上面的代码中:
第一行在heap对中创建内容为“abc”的对象,并建立abc到该对象的强引用,该对象是强可及的。
第二行和第三行分别建立对heap中对象的软引用和弱引用,此时heap中的对象仍是强可及的。
第四行之后heap中对象不再是强可及的,变成软可及的。同样第五行执行之后变成弱可及的。
1.2:软引用
软引用是主要用于内存敏感的高速缓存。在jvm报告内存不足之前会清除所有的软引用,
这样以来gc就有可能收集软可及的对象,可能解决内存吃紧问题,避免内存溢出。
什么时候会被收集取决于gc的算法和gc运行时可用内存的大小。当gc决定要收集软引用是执行以下过程,
以上面的abcSoftRef为例:
1 首先将abcSoftRef的referent设置为null,不再引用heap中的new String("abc")对象。
2 将heap中的new String("abc")对象设置为可结束的(finalizable)。
3 当heap中的new String("abc")对象的finalize()方法被运行而且该对象占用的内存被释放, abcSoftRef被添加到它的ReferenceQueue中。
注:对ReferenceQueue软引用和弱引用可有可无,但是虚引用必须有,参见:
Reference(T paramT, ReferenceQueue&? super T&paramReferenceQueue)
被 SoftReference 指到的对象,即使没有任何 Direct Reference,也不会被清除。
一直要到JVM内存不足且没有Direct Reference 时才会清除,SoftReference 是用来设计
object-cache 之用的。如此一来 SoftReference 不但可以把对象 cache 起来,也不会造成内存不足的错误 (OutOfMemoryError)。
我觉得 Soft Reference 也适合拿来实作 pooling 的技巧。
A obj = new A();
Refenrence sr = new SoftReference(obj);
if(sr!=null){
obj = sr.get();
obj = new A();
sr = new SoftReference(obj);
1.3:弱引用
当gc碰到弱可及对象,并释放abcWeakRef的引用,收集该对象。但是gc可能需要对此运用才能找到该弱可及对象。通过如下代码可以了明了的看出它的作用:
String abc = new String("abc");
WeakReference&String& abcWeakRef = new WeakReference&String&(abc);
System.out.println("before gc: "+abcWeakRef.get());
System.gc();
System.out.println("after gc: "+abcWeakRef.get());
gc收集弱可及对象的执行过程和软可及一样,只是gc不会根据内存情况来决定是不是收集该对象。
如果你希望能随时取得某对象的信息,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来记住此对象,而不是用一般的 reference。
A obj = new A();
WeakReference wr = new WeakReference(obj);
//等待一段时间,obj对象就会被垃圾回收
  if (wr.get()==null) {
   System.out.println("obj 已经被清除了 ");
  } else {
   System.out.println("obj 尚未被清除,其信息是 "+obj.toString());
在此例中,通过get()可以取得此Reference 的所指到的对象,如果返回值为 null 的话,
代表此对象已经被清除。这类的技巧,在设计 Optimizer 或 Debugger 这类的程序时常会用到,
因为这类程序需要取得某对象的信息,但是不可以影响此对象的垃圾收集。
1.4:虚引用
就是没有的意思,建立虚引用之后通过get方法返回结果始终为null,通过源代码你会发现,虚引用通向会把引用的对象写进referent,
只是get方法返回结果为null.先看一下和gc交互的过程在说一下他的作用.
1.4.1 不把referent设置为null, 直接把heap中的new String("abc")对象设置为可结束的(finalizable).
1.4.2 与软引用和弱引用不同, 先把PhantomRefrence对象添加到它的ReferenceQueue中.然后在释放虚可及的对象.
你会发现在收集heap中的new String("abc")对象之前,你就可以做一些其他的事情.通过以下代码可以了解他的作用.
2:在内存中压缩,对于少量不太大的图片这种方式可行,但太多而又大的图片用个笨的方式就是,
先在内存中压缩,再用软引用避免OOM,两种方式代码如下,大家可参考下:
private Bitmap copressImage(String imgPath){
File picture = new File(imgPath);
Options bitmapFactoryOptions = new BitmapFactory.Options();
//下面这个设置是将图片边界不可调节变为可调节
bitmapFactoryOptions.inJustDecodeBounds =
bitmapFactoryOptions.inSampleSize = 2;
int outWidth
= bitmapFactoryOptions.outW
int outHeight = bitmapFactoryOptions.outH
bmap = BitmapFactory.decodeFile(picture.getAbsolutePath(),bitmapFactoryOptions);
float imagew = 150;
float imageh = 150;
int yRatio = (int) Math.ceil(bitmapFactoryOptions.outHeight / imageh);
int xRatio = (int) Math.ceil(bitmapFactoryOptions.outWidth / imagew);
if (yRatio & 1 || xRatio & 1) {
if (yRatio & xRatio) {
bitmapFactoryOptions.inSampleSize = yR
bitmapFactoryOptions.inSampleSize = xR
bitmapFactoryOptions.inJustDecodeBounds =
bmap = BitmapFactory.decodeFile(picture.getAbsolutePath(),bitmapFactoryOptions);
if(bmap != null){
上面两种方式第一种直接使用边界压缩,第二种在使用边界压缩的情况下间接的使用了软引用来避免OOM,
但大家都知道,这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存,如果图片多且大,这种方式还是会引用OOM异常的,
不着急,有的是办法解决,继续看,以下方式也大有妙用的:
1. InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds =
options.inSampleSize = 10;
//width,hight设为原来的十分一
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2. if(!bmp.isRecycle() ){
bmp.recycle()
//回收图片所占的内存
system.gc()
//提醒系统及时回收
上面代码与下面代码大家可分开使用,也可有效缓解内存问题
/** 这个地方大家别搞混了,为了方便小马把两个贴一起了,使用的时候记得分开使用
* 以最省内存的方式读取本地资源的图片
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable =
opt.inInputShareable =
//获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is,null,opt);
3:大家可以选择在合适的地方使用以下代码动态并自行显式调用GC来回收内存:
if(bitmapObject.isRecycled()==false){ //如果没有回收
bitmapObject.recycle();
4:这个就好玩了,优化Dalvik虚拟机的堆内存分配,听着很强大,
private final static floatTARGET_HEAP_UTILIZATION = 0.75f;
在程序onCreate时就可以调用
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
5:自定义我们的应用需要多大的内存,这个好暴力哇,强行设置最小内存大小,代码如下:
private final static int CWJ_HEAP_SIZE = 6*
//设置最小heap内存为6MB大小
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
要避免内存泄露,主要要遵循以下几点:
  第一:不要为Context长期保存引用(要引用Context就要使得引用对象和它本身的生命周期保持一致)。
  第二:如果要使用到Context,尽量使用ApplicationContext去代替Context,因为ApplicationContext的生命周期较长,引用情况下不会造成内存泄露问题(除非是必须使用Context)
  第三:在你不控制对象的生命周期的情况下避免在你的Activity中使用static变量。尽量使用WeakReference去代替一个static。
  第四:垃圾回收器并不保证能准确回收内存,这样在使用自己需要的内容时,主要生命周期和及时释放掉不需要的对象。尽量在Activity的生命周期结束时,在onDestroy中把我们做引用的其他对象做释放,比如:cursor.close()。
浏览: 177869 次
来自: 贵州
增加事务处理
这也太小儿科了
大神,同上啊,没解决啊!appid跟1楼的一样,我也郁闷好几天 ...
前辈你好,我最近正在做微信分享,自己申请了appid,包名签名 ...
你就是救世主。
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 java out.println 的文章

 

随机推荐