我在读"C#语言",第四版,它谈论WeakReference和Weak Event Pattern:
CHRISTIAN NAGEL:内存泄漏通常是由于错误使用事件造成的.如果客户端对象附加到事件但不从它们分离,并且不再使用对客户端对象的引用,则垃圾回收器仍然无法回收客户端对象,因为发布者的引用仍然存在.这可以通过(1)在不再使用客户端对象时分离事件,(2)使用持有委托的类的自定义实现
add和/ 或(3)WPF使用IWeakEventListener来避免这种情况.接口.removeWeakReferenceWeak Event pattern
我在这里有疑问:选项"(2)WeakReference" 根本没有带来任何便利,与"选项(1)WeakReference明确地分离事件"相比,因为使用仍然需要显式调用两者add和remove.
否则,即使其中一个事件处理程序的对象被指定为null,"孤立"对象仍将响应该事件 - 这将导致意外行为.
注意:WeakReference仅以事件处理程序对象不会受事件发布者对象影响的方式帮助垃圾收集; WeakReference不强制事件处理程序对象被垃圾收集.
类似的问题也适用于弱事件模式.
也许这有点抽象,以Josh Smith的Mediator模式(http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/)为例.
public class Mediator //...
{
public void Register(object message, Action<object> callback)
{
// notice: Mediator has no Unregister method
}
public void NotifyColleagues(object message, object parameter)
{
// ...
}
}
public class ObjectA //...
{
public string …Run Code Online (Sandbox Code Playgroud) 我正在使用VisualVM分析我的应用程序,我发现堆大小在大约3天内增加了大约7MB.当我使用内存采样器时,我也看到它java.lang.ref.WeakReference在实例编号的前五位.数量WeakReference正在增加,GC几乎没有影响.
任何的想法?
我有一个连续运行的Windows服务,并创建一些线程来做一些工作.我想确保妥善处理这些线程(完成后收集垃圾).
但是,我也希望能够检查它们是否定期存活并且如果存在则终止它们.我知道我不能保留对它们的任何引用,因为那时它们不会被垃圾收集.
是否有另一种方法来检查用户定义线程的存在/状态?我想的可能是以下使用的东西WeakReference:(我现在无法完全测试,或者我只是自己测试)
List<WeakReference> weakReferences;
Thread myThread = new Thread(() => Foo());
WeakReference wr = new WeakReference(myThread);
weakReferences.Add(wr); //adds a reference to the thread but still allows it to be garbage collected
myThread.Start();
myThread = null; //get rid of reference so thread can be garbage collected
Run Code Online (Sandbox Code Playgroud)
然后在我的onTimeElapsed事件开始时(每5分钟运行一次):
foreach(WeakReference wr in weakReferences)
{
Thread target = wr.Target as Thread; //not sure if this cast is really possible
if(target.IsAlive && otherLogic)
{
target.Abort();
{
}
Run Code Online (Sandbox Code Playgroud)
但我不确定WeakReference是如何工作的.关于如何正确地做到这一点的任何想法?
MSDN:
弱引用对于使用大量内存的对象很有用,但如果它们被垃圾回收回收,则可以轻松地重新创建.
和
当您使用弱引用时,应用程序仍然可以获得对该对象的强引用,从而阻止其被收集.但是,在重新建立强引用之前,始终存在垃圾收集器首先到达对象的风险.
我的问题是:为什么可以轻松地重新创建WeakReference对象?GC发布后,与普通对象相比,可以轻松地重新创建吗?
我知道你应该在块中使用weakSelf,以避免保留内存周期.喜欢:
__weak id weakSelf = self;
self.block = ^{
[weakSelf something];
}
Run Code Online (Sandbox Code Playgroud)
但我正试图找到一种通用的方法.我可以使用像:
#define Weakify(o) __weak __typeof__((__typeof__(o))o)
#define WeakifySelf(o) Weakify(self) o = self;
WeakifySelf(weakSelf)
self.block = ^{
[weakSelf something];
}
Run Code Online (Sandbox Code Playgroud)
这简化了,但我想知道为什么我不能在我的viewController上使用ivar.
@interface YDViewController : UIViewController
{
__weak id _weakSelf;
}
Run Code Online (Sandbox Code Playgroud)
然后使用这个iVar
self.block = ^{
[_weakSelf something];
}
Run Code Online (Sandbox Code Playgroud)
任何的想法?
我正在使用Xcode 5.1.1为iOS 7.1编写一个小测试程序.我不使用XIB或故事板.一切都是以编程方式完成的.在AppDelegate.m中,我创建了一个TestViewController的实例,并将其设置为窗口的rootViewController.在TestViewController.m中,我覆盖"loadView"来创建和分配控制器的主视图.
TestViewController.h
--------------------
@interface TestViewController : UIViewController
@property (nonatomic, weak) UILabel *cityLabel ;
@end
TestViewController.m
--------------------
@implementation TestViewController
- (void)loadView
{
UIView *mainView = [[UIView alloc] init] ;
self.view = mainView ;
}
- (void) viewDidLoad
{
UIView *addressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)] ;
[self.view addSubview:addressView] ;
[self createCityLabel:addressView] ;
}
- (void) createCityLabel:(UIView *)addressView
{
// Warning for below line - Assigning retained object to weak property...
self.cityLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 80, …Run Code Online (Sandbox Code Playgroud) 我正在调查生产中的内存泄漏问题并检索内存转储.我试图抛弃累积物体的值,我遇到了WeakReference.这是我在WinDBG中得到的:
0:000> !do 000000011a306510
Name: System.WeakReference
MethodTable: 000007feeb3f9230
EEClass: 000007feeadda218
Size: 24(0x18) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007feeb3f4a00 400068d 8 System.IntPtr 1 instance 343620e0 m_handle
0:000> !do 343620e0
<Note: this object has an invalid CLASS field>
Invalid object
Run Code Online (Sandbox Code Playgroud)
我们可以发现我们不能将该m_handle值用作对象地址.我检查了代码,WeakReference它是完全extern代码.
我的问题是,我们如何使用WinDBG/SOS检查它的价值?另外,我正在为ClrMD的问题编写ad-hoc分析器,那么我应该如何检查对象的对象引用WeakReference呢?
我试着理解课堂 ReferenceQueue
它是可选的构造函数参数
SoftReference
Run Code Online (Sandbox Code Playgroud)
和
WeakReference
Run Code Online (Sandbox Code Playgroud)
它也是 的强制性参数PhantomReference。
根据我读过的信息,我可以写一些论文
a) 对于 PhantomReference 方法 get 总是返回 null
b)
对于 Phantom 引用:
1. gc 检测到该对象可以从内存中删除
2. 对放入 ReferenceQueue 的对象的引用,
当我们调用 clear 或 link to reference from queue 时无法访问并且 gc 看到 3. finalize 方法调用
4.
为弱/软引用释放内存:
1. gc 检测到该对象可以从内存中删除
2. 终结方法调用
3. 释放内存
4. 对放入队列的对象的引用
XXXReference构造函数?PhantomReference没有没有构造函数ReferenceQueue?我想知道是否有一种简单的方法(或至少是一种方法)来找出程序中存在保留周期的位置.此外,如果我知道这些保留周期存在的位置,取决于它们的类型(例如变量或闭包),我该如何使它们变弱.我需要使用self(我的GameScene)停止所有保留周期,以便在我不再需要它时解除分配并且我想重新启动它.
任何提示,建议,答案和反馈将不胜感激(并提供特定的代码和示例将是首选).谢谢.
编辑: @ Sweeper的回答正是我想要的.如果你遇到同样的问题,他的回答会有所帮助.谢谢@Sweeper!
我是 Java 的新手。我现在正在学习 WeakReference 的概念。我遇到了一个可能看起来很愚蠢的问题,但我只是想找出原因。问题是:根据 Java 文档,“弱引用对象,它不会阻止其所指对象被终结、终结和回收。”
所以我做了这个小测试:
import java.lang.ref.WeakReference;
public class A {
public static void main(String[] args) {
A a = new A();
WeakReference<A> wr = new WeakReference<>(a);
a = null;
A a1 = wr.get();
System.out.println(a);
System.out.println(a1);
try {
System.gc();
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(a1);
}
@Override
protected void finalize( ) {
System.out.println(Thread.currentThread().getName() + ": See ya, nerds!");
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我注意到在 GC 运行后,wr.get()仍然可以返回我期望为 null 的对象,并且finalize()没有调用该方法。那么出了什么问题呢?提前感谢您的帮助!:)
weak-references ×10
java ×3
c# ×2
ios ×2
memory-leaks ×2
objective-c ×2
.net ×1
clrmd ×1
reference ×1
retain-cycle ×1
sos ×1
sprite-kit ×1
swift ×1
swift3 ×1
weak-events ×1
windbg ×1