`

理解 弱引用(Weak References)

阅读更多

原文 :https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html  

Posted by enicholas on May 4, 2006 at 5:06 PM PDT

 

Understanding Weak References

理解 弱引用(Weak References)  

 

Some time ago I was interviewing candidates for a Senior Java Engineer position. 

Among the many questions I asked was "What can you tell me about weak references?"

I wasn't expecting a detailed technical treatise on the subject.

 

一段时间之前,我曾面试过一位求职者,他申请的职位是Java高级工程师. 

我问他的诸多问题中,有一个问题是这样的:"请你谈谈弱引用(weak references)". 

对于这个问题,我并不期待类似教科书般的技术细节之类的回答.

 

I would probably have been satisfied with "Umm... don't they have something to do with garbage collection?" 

I was instead surprised to find that out of twenty-odd engineers, 

all of whom had at least five years of Java experience and good qualifications,

only two of them even knew that weak references existed, and only one of those two had actual useful knowledge about them.

I even explained a bit about them, to see if I got an "Oh yeah" from anybody -- nope.

 

假如听到"呃,它们是不是跟垃圾回收有关?"这样的回答,我可能就表示满意了.

相反,我感到很奇怪,因为在20多个至少拥有5年Java使用经验并且具有良好资质的工程师中 

只有2个人了知道有弱引用(weak references)存在这回事,并且2人当中也只有其中一个人了解一些真正有用的与弱引用相关知识.

我甚至给他们做了一些解释,以期待得到"哦,我想起来了..."之类的回答,但是没有.

 

I'm not sure why this knowledge is (evidently) uncommon, as weak references are a massively useful feature 

which have been around since Java 1.2 was released, over seven years ago.

Now, I'm not suggesting you need to be a weak reference expert to qualify as a decent Java engineer. 

But I humbly submit that you should at least know what they are -- otherwise how will you know when you should be using them? 

Since they seem to be a little-known feature, here is a brief overview of what weak references are, how to use them, and when to use them.

 

我不知道这些知识看起来有什么高深的(不普通的),因为弱引用这种相当有用的特性在7年前Java1.2发布的时候就出现了.

我不期待你像资深Java工程师一样成为弱引用方面的专家.

但是,至少你应该了解他们是什么,不然怎么知道什么时候该用它们呢?

鉴于弱引用看起来似乎是一个鲜为人知的特性,这里简要介绍下什么是弱引用,该如何使用以及何时应该使用他们.

 

 

Strong references

强引用

 

First I need to start with a refresher on strong references. 

A strong reference is an ordinary Java reference, the kind you use every day. For example, the code: 

StringBuffer buffer = new StringBuffer(); 

creates a new StringBuffer() and stores a strong reference to it in the variable buffer. 

Yes, yes, this is kiddie stuff, but bear with me. The important part about strong references -- the part that makes them "strong" -- 

is how they interact with the garbage collector. 

Specifically, if an object is reachable via a chain of strong references (strongly reachable), it is not eligible for garbage collection.

As you don't want the garbage collector destroying objects you're working on, this is normally exactly what you want.

 

首先,从强引用开始,强引用就是常规的引用,我们每天都使用的.例如,

StringBuffer buffer = new StringBuffer(); 

上面的代码:创建了一个新的StringBuffer对象,并且把这个对象的 强引用 存储在buffer变量中.

是的,是的,这看起来像小儿科,但是请稍安勿躁,跟我一起继续看:强引用中最重要的部分--就是让引用变"强"的部分--是引用如何与垃圾回收器交互的.

明确的说,如果一个对象通过强引用链是可到达的(强可到达),那么这个对象就不会被垃圾回收器选中回收. 

这正是你想要的,因为你不想让你正在使用的对象被垃圾回收器回收.

 

When strong references are too strong

当引用太"强"

 

It's not uncommon for an application to use classes that it can't reasonably extend. 

The class might simply be marked final, or it could be something more complicated, such as an interface returned by a factory method backed 

by an unknown (and possibly even unknowable) number of concrete implementations. 

 

Suppose you have to use a class Widget and, for whatever reason, it isn't possible or practical to extend Widget to add new functionality.

What happens when you need to keep track of extra information about the object?

 

通常,需要在程序中使用不可被继承的类.

这些不可被继承的类可能仅仅是被设置成final的类,或者更复杂的类,比如一些接口的实现类,

这些类是通过一些未知(甚至可能是不可知)数目的工厂方法接口的具体实现类返回的.

设想下你需要使用一个Widget类,因为某种原因,这个Widget类不能通过继承以添加新的功能.

当你需要跟踪这些Widget对象的一些额外信息时,该怎么做呢?

 

In this case, suppose we find ourselves needing to keep track of each Widget's serial number, 

but the Widget class doesn't actually have a serial number property -- and because Widget isn't extensible, we can't add one. 

No problem at all, that's what HashMaps are for:

 

例如,我们需要追踪每一个Widget对象的序列号属性,

但是Widget类实际上没有序列号这个属性,并且因为Widget类无法被继承,我们也就不能为Widget添加一个序列号属性.

这样的问题,使用HashMap似乎可以解决:

 

serialNumberMap.put(widget, widgetSerialNumber);

 

This might look okay on the surface, but the strong reference to widget will almost certainly cause problems. 

We have to know (with 100% certainty) when a particular Widget's serial number is no longer needed, so we can remove its entry from the map. 

Otherwise we're going to have a memory leak (if we don't remove Widgets when we should) or 

we're going to inexplicably find ourselves missing serial numbers (if we remove Widgets that we're still using).

从表面上看,这样的代码似乎能正常工作,但是对widget的强引用几乎注定会出问题.

我们知道(可以100%确信)当一个特定的Widget序列号不再需要时,我们可以从map中移除一个entry.

然而,这么做可能会导致内存泄露(假如我们没有在需要移除Widget对象的时候将其从map中移除(注,这里Widget对象是作为map的key的)),

或者,可能会发现丢失了序列号(假如我们将仍在使用的Widget对象从map中移除了).

 

(译注: 内存泄漏原因,Map这个引用一直存在,而Map中的有的Entry可能不需要了,但是没有及时的从Map中移除,这些Enty占用的内存空间就浪费了,造成了内存泄漏.)

 

If these problems sound familiar, they should: they are exactly the problems that users of non-garbage-collected languages face when trying to manage memory, 

and we're not supposed to have to worry about this in a more civilized language like Java. 

Another common problem with strong references is caching, particular with very large structures like images. 

 

Suppose you have an application which has to work with user-supplied images, 

like the web site design tool I work on. Naturally you want to cache these images, 

because loading them from disk is very expensive and you want to avoid 

the possibility of having two copies of the (potentially gigantic) image in memory at once.

 

下面这个说法是不是很耳熟呢:这种问题是那些无垃圾回收机制语言(注:如C++)的使用者们在处理内存管理时需要考虑的,

而像Java这样更高级语言的使用者们无需担心这样的问题.

 

另外一个与强引用相关的问题是缓存,尤其是像一些类似图片的大存储结构缓存.

设想下你正在开发一款程序用来处理用户提供的图片,就像我现在正在做的web站点开发工具程序一样.

通常,你会缓存用户的图片,因为从磁盘加载图片代价相当昂贵,

并且你也不希望在内存中同时保留这些图片的双份拷贝(这些拷贝的尺寸通常都是相当巨大的).

 

Because an image cache is supposed to prevent us from reloading images when we don't absolutely need to,

you will quickly realize that the cache should always contain a reference to any image which is already in memory.

With ordinary strong references, though, that reference itself will force the image to remain in memory,

which requires you (just as above) to somehow determine when the image is no longer needed in memory and 

remove it from the cache, so that it becomes eligible for garbage collection. 

Once again you are forced to duplicate the behavior of the garbage collector and 

manually determine whether or not an object should be in memory.

 

因为图片缓存是用来防止我们在并不需要加载图片时重复加载, 

你很快会发现缓存对象需要一直持有对内存中每一张图片对象的引用.

然而,常规的强引用强制地让这些图片缓存一直保留在内存中,

这就要求你自己决定什么时候这些图片不再需要留在内存中了,

然后再手工将其从图片缓存中移除,以便这个图片缓存能被垃圾回收器选中回收.

这样你不得不重复做着垃圾回收应该做的事,并且手工设定是否让一个对象留在内存中.

 

Weak references

弱引用

 

A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. 

Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. 

You create a weak reference like this:

 

弱引用,简单的说,就是一个引用不够强壮,以至于不能保证它指向的对象一直留在内存中.

弱引用允许你借助垃圾回收器来决定对象的可到达性,因而你不用自己手动实现(即,对应上面的需要手工处理那些图片不用再留在内存中).

你可以用这种方式创建弱引用:

 

WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget);

 

and then elsewhere in the code you can use weakWidget.get() to get the actual Widget object. 

Of course the weak reference isn't strong enough to prevent garbage collection, so you may find 

(if there are no strong references to the widget) that weakWidget.get() suddenly starts returning null.

 

然后,在你的代码的任何地方,你可以使用weakWidget.get()来获取真正的Widget对象.

当然,因为弱引用不够"强壮",不足以阻止垃圾回收器的回收,所以你可能会发现(当没有强引用指向widget对象时)weakWidget.get()会突然返回null.

 

To solve the "widget serial number" problem above, the easiest thing to do is use the built-in WeakHashMap class. 

WeakHashMap works exactly like HashMap, except that the keys (not the values!) are referred to using weak references.

If a WeakHashMap key becomes garbage, its entry is removed automatically. 

This avoids the pitfalls I described and requires no changes other than the switch from HashMap to a WeakHashMap. 

If you're following the standard convention of referring to your maps via the Map interface, 

no other code needs to even be aware of the change.

 

解决上文中的"widget对象的序列号"问题的最简单方法是使用JDK内建的WeakHashMap类.

WeakHashMap的工作方式与HashMap十分类似,但是HashMap的keys(键,不是值(values))是使用弱引用的.

如果WeakHashMap的一个key变成垃圾,则与之相关的entry将被自动从Map中移除.

这就避免了上文所述的使用普通HashMap导致的内存泄露陷阱,需要做的仅仅是将HashMap替换为WeakHashMap.

如果你的代码符合使用map的标准规范,即,通过Map接口来引用你的map,就没有其他代码需要修改(需要做的仅仅是将HashMap替换为WeakHashMap).

 

 

Reference queues

引用队列

 

Once a WeakReference starts returning null, the object it pointed to has become garbage and the WeakReference object is pretty much useless. 

This generally means that some sort of cleanup is required; WeakHashMap, for example, 

has to remove such defunct entries to avoid holding onto an ever-increasing number of dead WeakReferences.

 

一旦一个弱引用(WeakReference)开始返回null,WeakReference指向的对象即变成垃圾,这样WeakReference对象(注:这里是指弱引用对象本身吧?)就变得毫无用处了.

这就意味着需要做一些清理工作了,比如WeakHashMap需要移除已经死亡的实体(entry)以避免持有数量不断增加且已经死亡的弱引用.

 

The ReferenceQueue class makes it easy to keep track of dead references. 

If you pass a ReferenceQueue into a weak reference's constructor, the reference object will be automatically 

inserted into the reference queue when the object to which it pointed becomes garbage. 

You can then, at some regular interval, process the ReferenceQueue and perform whatever cleanup is needed for dead references.

 

使用ReferenceQueue类可以轻松追踪死亡引用(注:死亡的弱引用对象本身).

如果传递一个ReferenceQueue对象给弱引用的构造函数,那么当弱引用对象指向的对象变成可回收的垃圾时,这个弱引用对象(注:弱引用对象本身)将被自动插入到引用队列中.

这时,你可以隔一段时间就遍历ReferenceQueue对象,为已死亡的弱引用对象做一些必要的清理工作.

 

 

Different degrees of weakness

弱引用的不同等级

 

Up to this point I've just been referring to "weak references", but there are actually 

four different degrees of reference strength: strong, soft, weak, and phantom, 

in order from strongest to weakest. We've already discussed strong and weak references, 

so let's take a look at the other two.

 

到目前为止,我仅仅使用了"弱引用"一词.但事实上,一共有4个等级的引用强度,

从强到弱依次为:强引用,软引用,弱引用和虚幻(或者魔鬼,幽灵?)引用.

我们已经讨论过强引用和弱引用了,接下来我们来看看剩下的两种.

 

Soft references

软引用

 

A soft reference is exactly like a weak reference, except that it is less eager to 

throw away the object to which it refers. 

An object which is only weakly reachable (the strongest references to it 

are WeakReferences) will be discarded at the next garbage collection cycle, 

but an object which is softly reachable will generally stick around for a while.

 

软引用和弱引用十分类似,但软引用不像弱引用那样轻易的抛弃它所指向的对象.

一个仅仅可弱到达的对象(指向这个对象最强的引用是弱引用(WeakReference))将在下次垃圾回收循环时被回收,

但软可到达对象仅仅在内存中保留一段时间(即,很容易被回收).

(注:具体的回收要看JVM垃圾回收器的算法了,一般软引用对象的对象在Heap内存快要消耗光即将抛出OutOfMemory时回收,

而弱引用指向的对象可在任何时间回收)

 

SoftReferences aren't required to behave any differently than WeakReferences, 

but in practice softly reachable objects are generally retained as long as memory is in plentiful supply.

 

软引用与弱引用并没有任何不同的行为,但是一般情况下软可到达对象(软引用指向的对象)会在JVM的堆内存不足时被回收

(注:即一直在内存中保留着,指导内存不足了才会回收).

 

This makes them an excellent foundation for a cache, such as the image cache described above, 

since you can let the garbage collector worry about both how reachable the objects are

(a strongly reachable object will never be removed from the cache) and how badly it needs the memory they are consuming.

 

软引用的这些特性使得它是作为缓存的理想结构,比如可作为上文中提到的图片缓存.

因为你可以让垃圾回收器来处理对象是否保留在内存中与该对象严重消耗内存之间的平衡(一个强可到达对象将永远不会从缓存中移除).

(注:这段貌似意思翻译的不太好,有点说不清,求指正.)

 

Phantom references

虚幻(或者魔鬼,幽灵?)引用

 

A phantom reference is quite different than either SoftReference or WeakReference. 

Its grip on its object is so tenuous that you can't even retrieve the object -- its get() method always returns null. 

The only use for such a reference is keeping track of when it gets enqueued into a ReferenceQueue, 

as at that point you know the object to which it pointed is dead. 

 

虚幻引用与前面说的软引用和弱引用都相当滴不同.

虚幻引用对它引用的对象的把控能力相当脆弱,以至于你都不能通过他的get()方法获取虚幻引用所指向的对象(注:因为get()总是返回null).

这种引用的唯一用处是,当虚幻引用对象被加入到引用对列后,保持对虚幻引用对象的跟踪,因为在那时你知道虚幻引用所指向的对象已经挂了.

 

How is that different from WeakReference, though?

The difference is in exactly when the enqueuing happens. 

WeakReferences are enqueued as soon as the object to which they point becomes weakly reachable. 

This is before finalization or garbage collection has actually happened; in theory the object could even be "resurrected" 

by an unorthodox finalize() method, but the WeakReference would remain dead. 

PhantomReferences are enqueued only when the object is physically removed from memory, 

and the get() method always returns null specifically to prevent you from being able to "resurrect" an almost-dead object.

 

那么,虚幻引用和弱引用有什么不同呢? 答:其不同点在于引用对象何时加入引用队列.

只要弱引用对象指向的对象变得弱可到达,这个弱引用对象即被加入引用队列,这个过程在finalization和垃圾回收发生之前;

理论上说,此时的对象甚至可以通过非正常的finalize()方法调用实现复活,但是弱引用对象仍然是死亡的.

 

虚幻引用对象只在它指向的对象真正从内存中移除时才进入引用队列

(注:就是说,一旦虚幻引用指向的对象真正从内存中移除了,这个对象就会放入到引用队列中,

而软引用和弱引用的get()方法返回null时,软引用或者弱引用对象才被放入到引用队列中),

并且虚幻引用的get()方法的返回值都是null,以此来阻止你复活一个几乎快挂了的对象.

 

What good are PhantomReferences? I'm only aware of two serious cases for them: first, 

they allow you to determine exactly when an object was removed from memory. 

They are in fact the only way to determine that. This isn't generally that useful, 

but might come in handy in certain very specific circumstances like manipulating large images: 

if you know for sure that an image should be garbage collected, you can wait until it 

actually is before attempting to load the next image, and therefore make the dreaded OutOfMemoryError less likely.

 

这个虚幻引用有什么优点? 我仅仅关注两个重要方面:

首先,虚幻引用可以让我们准确地知道对象是何时被从内存中删除的.

使用虚幻引用也是唯一一种方式使得你可以准确地知道对象是何时被从内存中删除的.

这个看起来可能不那么有用,但是在特定的场景下可能非常方便,比如操作大图片:

如果你确切地知道一个图片何时应该被垃圾回收器回收,那么你就可以等到它真正的被回收了以后再尝试载入下一个图片,

这样像恐怖的OutOfMemoryError这类错误的发生几率就会下降.

 

 

Second, PhantomReferences avoid a fundamental problem with finalization: 

finalize() methods can "resurrect" objects by creating new strong references to them. 

So what, you say? Well, the problem is that an object which overrides finalize() 

must now be determined to be garbage in at least two separate garbage 

collection cycles in order to be collected. When the first cycle determines 

that it is garbage, it becomes eligible for finalization. 

Because of the (slim, but unfortunately real) possibility that the object 

was "resurrected" during finalization, the garbage collector has to run again 

before the object can actually be removed. And because finalization might 

not have happened in a timely fashion, an arbitrary number of garbage 

collection cycles might have happened while the object was waiting for finalization. 

This can mean serious delays in actually cleaning up garbage objects, and is why 

you can get OutOfMemoryErrors even when most of the heap is garbage.

 

其次,虚幻引用可以避免使用finalization带来根本问题:

finalize()方法中可以创建一个新的强引用指向对象,从而导致对象"复活".

上面说的到底嘛意思好吧,其实问题就是一个对象覆盖了finalize()方法的对象可能需要两轮的垃圾回收过程后才能被回收.

当第一轮垃圾回收确定这个对象可回收后,就需要执行它的清理工作(注:finalization,在finalize()方法中完成).

因为有可能(可能性比较小,但不幸的是有可能)这个本该被回收的对象在清理时(注:在finalize()方法中)复活了,

这样垃圾回收器需要再执行一次才能真正从内存中移除这个对象.

并且,因为最终的清理可能不会及时进行,这样就导致大量的垃圾清理过程都在等待垃圾的清理.

这就意味着垃圾真正垃圾对象的清理被严重推迟,结果就是明明JVM内有很多Garbage却OutOfMemory.

(注:参考:http://m.oschina.net/blog/83503)

 

With PhantomReference, this situation is impossible -- when a PhantomReference is enqueued, 

there is absolutely no way to get a pointer to the now-dead object (which is good, 

because it isn't in memory any longer). Because PhantomReference cannot be used to resurrect an object, 

the object can be instantly cleaned up during the first garbage collection cycle in 

which it is found to be phantomly reachable. 

You can then dispose whatever resources you need to at your convenience.

 

使用虚幻引用,上面的问题即可避免,因为当虚幻引用对象进入引用队列后,

就不可能通过任何方法再获取虚幻引用指向的实际上已经挂了的对象了.

因为虚幻引用不能使一个对象复活,在这个对象被标记为虚可到达(phantomly reachable)后,在第一轮的垃圾清理中即被清除.

虚幻引用指向的对象被清理后,你就可以方便的加载任何其他资源了.

 

Arguably, the finalize() method should never have been provided in the first place. 

PhantomReferences are definitely safer and more efficient to use, and eliminating finalize() 

would have made parts of the VM considerably simpler. 

But, they're also more work to implement, so I confess to still using finalize() most of the time. 

The good news is that at least you have a choice.

 

按理说,我们不应该使用finalize()方法的.使用虚幻引用绝对是一个更安全和有效的方式,

而且取消finalize()方法也使得虚拟机处理起来更简单些(注:虚拟机垃圾回收时更简单些,不用finalize).

但是取代finalize()后,有更多的额外工作要做,所以我承认大部分时间我还是使用了finalize()方法,

好消息是,使用虚幻引用时,我们至少多了一个选择(注:本来使用finalize()方法,现在可以使用虚幻引用了?).

 

Conclusion

总结:

 

I'm sure some of you are grumbling by now, 

as I'm talking about an API which is nearly a decade old and haven't said anything which hasn't been said before. 

While that's certainly true, in my experience many Java programmers really don't know very much (if anything) about weak references, 

and I felt that a refresher course was needed. Hopefully you at least learned a little something from this review.

 

我敢肯定好多人到目前为止还在抱怨,因为我不过是讨论了一个有十几年历史的API而已,并没有谈论任何以前没被讨论过的东西.

但是据我所知,好多Java程序员确实不知道太多的(几乎任何)与弱引用相关的知识,

我觉得与之相关的一些进修课程是必须的.希望通过这篇文章你至少了解一点关于弱引用的知识.

 

(注:总结:

  

  1. 弱引用,软引用 指向的对象会被自动回收,但是软引用指向的对象仅在Heap内存即将不足的时候回收,而弱引用指向的对象可在任何时候被回收

  2. 弱引用,软引用的get()方法返回null后,软引用,软引用对象本身即被加入到引用队列(如果它们在构造时注册了引用队列的话)

  3. 弱引用,软引用对象本身在加入到引用队列后,它们指向的对象的finalize方法和回收操作还没有进行.

  

  4. 虚幻引用 指向的对象不会自动被回收,需要手工处理,但是一旦虚幻引用指向的对象被回收了,虚幻引用对象本身才会被加入到引用队列(虚幻对象引用队列必须要有),

  5. 虚幻引用对象在加入引用队列后,它所指向的对象的finalize方法和回收操作都已经完成了.也就是说,只有在虚幻引用对象指向的对象真正的从内存中移除了,

     虚幻引用对象才会加入到引用队列中

)

 附一个 虚幻引用何时加入 引用队列的 列子

 

    

public class Bean
{
  private String name;
  private int age;
  
  public Bean(String name, int age)
  {
    this.name = name;
    this.age = age;
  }

  public String getName()
  {
    return name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

  public int getAge()
  {
    return age;
  }

  public void setAge(int age)
  {
    this.age = age;
  }
  
  @Override
  public String toString()
  {
    return "Bean: name=" + this.name + ", age=" + age;
  }
}

 

 

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;


/**
 * 虚引用有以下特征:
 * 虚引用永远无法使用 get() 方法取得对象的强引用从而访问目标对象。
 * 虚引用所指向的对象在被系统内存回收前,虚引用自身会被放入 ReferenceQueue 对象中从而跟踪对象垃圾回收。
 * 虚引用不会根据内存情况自动回收目标对象。
 * 另外值得注意的是,其实 SoftReference, WeakReference 以及 PhantomReference 的构造函数都可以接收一个 ReferenceQueue 对象。
 * 当 SoftReference 以及 WeakReference 被清空的同时,也就是 Java 垃圾回收器准备对它们所指向的对象进行回收时,
 * 调用对象的 finalize() 方法之前,它们自身会被加入到这个 ReferenceQueue 对象中,
 * 此时可以通过 ReferenceQueue 的 poll() 方法取到它们。
 * 而 PhantomReference 只有当 Java 垃圾回收器对其所指向的对象真正进行回收时,
 * 会将其加入到这个 ReferenceQueue 对象中,这样就可以追综对象的销毁情况。
 *
 */
public class TestPhantomReference
{
  public static void main(String[] args)
  {
    ReferenceQueue<Bean> refQueue = new ReferenceQueue<Bean> ();
    
    Bean aBean = new Bean("Jack",29); //aBean 是一个强引用 指向new出来的对象
    
    PhantomReference<Bean> referent  = new PhantomReference<Bean>(aBean,refQueue);
    System.out.println(referent.get()); //虚引用PhantomReference的get()永远返回null
    System.gc(); //因为 aBean强引用,new Bean("Jack",29); 不能回收
    System.runFinalization();
    System.out.println(refQueue.poll()==referent);//false,因为aBean是强引用,这样referent对象还没有被放到引用队列中
    
    aBean = null; //这样new出来的 对象可被回收了
    System.gc(); //回收 new Bean("Jack",29);回收后referent 指向的对象被回收,于是referent被加入到引用队列
    System.runFinalization();
    System.out.println(refQueue.poll()==referent);//true,
  }
}

    

 

分享到:
评论

相关推荐

    PHP7扩展向PHP添加了SoftandWeak引用支持

    其次,弱引用(Weak References)比软引用更弱,它完全不会影响对象的生命周期。持有弱引用的对象可以在任何时候被垃圾收集器清理,即使存在弱引用。弱引用主要用于那些不希望影响对象生命周期,但又需要在某些时刻...

    Android JNI引用类型管理 (十)

    **弱全局引用(Weak Global References)** 弱全局引用与全局引用相似,也是用来保持对Java对象的长时间引用,但有一个关键区别:弱全局引用不会阻止垃圾收集器回收目标对象。即使有弱全局引用指向一个对象,只要...

    swift-快速定位Block循环引用所处位置

    `weak`创建一个可选的弱引用,如果对象被释放,弱引用会变为nil。`unowned`则假设引用的对象不会先于Block被释放,因此不会检查是否为nil,这在确定对象生命周期的情况下更有效率。 5. **自定义Dealloc方法**:在类...

    swift学习第三章

    Swift提供了弱引用(Weak References)和无主引用(Unowned References)来解决这个问题。弱引用不会阻止引用的对象被释放,而无主引用假设引用的对象不会提前释放,从而避免循环引用。合理地使用这些特性可以确保...

    从零开始学iOS7开发系列3-我的地盘我做主-Cha201

    另一方面,弱引用(Weak References)用于打破对象之间的强引用循环。例如,视图控制器的outlet属性通常声明为weak,因为它们并不真正拥有对应的视图,视图是其父视图的一部分。这样可以防止出现循环引用,例如,当...

    多线程内存管理

    在Objective-C中,这通常通过弱引用(weak references)来解决,弱引用不会增加对象的引用计数,因此当对象的强引用释放后,弱引用指向的对象也可以被ARC安全地回收。 虽然ARC极大地简化了内存管理,但程序员仍然...

    IOS内存管理与软件调试

    解决循环引用通常需要使用弱引用(Weak References)或无主引用(Unowned References)。 另外,iOS中的内存管理还包括了解内存的三个区域:堆(Heap)、栈(Stack)和内联存储(BSS/Static)。栈内存由系统自动...

    电子书 深入理解C++11(PDF)

    2. **右值引用(Rvalue References)**:右值引用用于处理临时对象和移动语义,提高了效率。`std::move`函数可以将左值转换为右值引用,允许资源的有效转移,是实现`RAII(Resource Acquisition Is Initialization)`...

    IOS应用源码——RetainCount.rar

    解决这个问题可以使用弱引用(`__weak`)或无主引用(`__unsafe_unretained`)。 6. **NSManagedObjects与Core Data**:在使用Core Data时,`NSManagedObjects`有特殊的内存管理规则。它们通常由上下文管理,而不是...

    iOS开发高级知识.zip

    2. **ARC(Automatic Reference Counting)**:iOS中的内存管理主要依赖于ARC,理解引用计数和循环引用的概念,以及如何使用弱引用(Weak References)和无主引用(Unowned References)来避免内存泄漏至关重要。...

    jdk版本11win64位

    6. **改进的内存模型**: 引入了强引用(StrongReferences)、软引用(SoftReferences)、弱引用(WeakReferences)和虚引用(PhantomReferences)的改进,提供了更好的垃圾回收策略。 7. **JLink 和 JPackage**: 这...

    西安电脑技术培训华美校区教授使用的6个Java功能.docx

    5. **弱引用/软引用(Weak/Soft references)**:这些引用类型用于缓存策略,当内存紧张时,弱引用对象会被GC自动清除。然而,基于软引用的缓存可能导致反复创建和销毁对象,从而增加内存压力和CPU使用率,形成性能...

    握柄

    在Rust中,"握柄"可以分为弱引用(Weak References)和强引用(Strong References)。强引用是默认的引用类型,它保持对值的所有权,直到没有其他强引用指向该值时才会释放。弱引用则不拥有值,即使存在弱引用,值也...

    iPhone 应用开发中Object-C 内存管理--千锋培训

    为了解决这个问题,Objective-C引入了弱引用(weak reference)和强引用(strong reference)的概念,以及ARC(Automatic Reference Counting)技术,自动处理对象间的引用关系,防止循环引用的发生。 在实际开发中,理解...

    深入理解 C++ 11 PDF文档

    2. **右值引用(Rvalue References)**:右值引用是用来处理临时对象的引用类型,是C++ 11中的一个重要概念。通过右值引用,可以实现移动语义(Move Semantics),有效利用资源,提高程序性能。 3. **Lambda表达式*...

    深入理解C++11:C++11新特性解析与应用(62M高清扫描版)

    C++11引入了右值引用(Rvalue References)和移动语义(Move Semantics),这是为了优化对象的构造和拷贝过程。通过使用`&&`符号声明右值引用,可以创建临时对象的引用,从而在某些情况下实现更高效的数据转移,比如...

    The Swift Programming Language 书籍英文原版 PDF及EPUB版本

    5. **内存管理**:了解引用计数(reference counting)与自动引用计数(ARC)以及无主引用(unowned references)和弱引用(weak references)。 6. **函数式编程**:Swift支持高阶函数(higher-order functions)...

    Flex 有效的内存回收方法

    2. **Weak References**: 在Flex中,可以使用WeakReference类来创建弱引用。弱引用不会阻止对象被垃圾收集,即使有其他强引用指向该对象。这在处理事件监听器时特别有用,因为不当的监听器处理可能导致内存泄漏。 3...

Global site tag (gtag.js) - Google Analytics