- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我们的系统中,我们将客户端 session 呈现为类 session 。
从历史上看,此类的哈希码是可变的 - 它在创建时为 0,并在某个时间点更改为用户 ID。
系统中存在两个 session 管理器。
当客户端连接并登录时,下一个流程发生:
作为收集 Session 对象上所有强引用后的结果,它必须从 WeakHashMap 中删除。(WeakHashMap 中的条目将在以下情况下自动删除 它的 key 不再正常使用。更准确地说,存在一个 给定键的映射不会阻止键被丢弃 垃圾收集器,也就是说,使其可终结、终结,然后回收。)但出于某种原因,他们留在那里。代码如下:
public class MemorySessionManager implements Runnable {
private static final Logger logger = LoggerFactory.getLogger("checker");
private Map<Session, Long> sessions;
public MemorySessionManager() {
this.sessions = new WeakHashMap<>();
}
public synchronized void addSession(Session sess) {
sessions.put(sess, sess.getId());
}
public void run() {
Set<Session> sessionsToCheck = new HashSet<>();
synchronized (this) {
sessionsToCheck.addAll(sessions.keySet());
}
for (Session sess : sessionsToCheck) {
logger.warn("MemorySessionManager: Is still here: " + sess);
}
}
}
简化的程序流程和 session 类(没有无用的信息)。
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ClientSessionManager {
private Map<Long, Session> sessions;
public ClientSessionManager() {
this.sessions = new ConcurrentHashMap<>();
}
public void addSession(Session session) {
sessions.put(session.getUserId(), session);
}
public Session removeSession(long code) {
return sessions.remove(code);
}
}
public class Session {
private long userId;
public void setUserId(long userId) {
this.userId = userId;
}
public long getUserId() {
return userId;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Session session = (Session) o;
return userId == session.userId;
}
@Override
public int hashCode() {
return (int) (userId ^ (userId >>> 32));
}
}
public class Process {
private static final ClientSessionManager CLIENT_SESSION_MANAGER = new ClientSessionManager();
private static final MemorySessionManager MEMORY_SESSION_MANAGER = new MemorySessionManager();
/**
* Login user, create its session and register session into appropriate managers.
*
* @param userId id of user
*/
public void login(long userId) {
Session session = new Session();
MEMORY_SESSION_MANAGER.addSession(session);
session.setUserId(userId);
CLIENT_SESSION_MANAGER.addSession(session);
}
/**
* Close session of user, remove it from session manager
*
* @param userId id of user
*/
public void close(long userId) {
CLIENT_SESSION_MANAGER.removeSession(userId);
}
}
经过大量 GC 循环后,in 仍保留在内存中。这是 GC 上的日志(G1,混合)
[GC pause (G1 Evacuation Pause) (mixed)
Desired survivor size 6815744 bytes, new threshold 4 (max 15)
- age 1: 236400 bytes, 236400 total
- age 2: 350240 bytes, 586640 total
- age 3: 3329024 bytes, 3915664 total
- age 4: 2926992 bytes, 6842656 total
, 0.0559520 secs]
[Parallel Time: 51.9 ms, GC Workers: 2]
[GC Worker Start (ms): Min: 73278041.7, Avg: 73278041.8, Max: 73278042.0, Diff: 0.2]
[Ext Root Scanning (ms): Min: 3.2, Avg: 3.4, Max: 3.7, Diff: 0.5, Sum: 6.9]
[Update RS (ms): Min: 15.0, Avg: 15.0, Max: 15.0, Diff: 0.0, Sum: 30.1]
[Processed Buffers: Min: 59, Avg: 65.0, Max: 71, Diff: 12, Sum: 130]
[Scan RS (ms): Min: 13.6, Avg: 14.3, Max: 15.1, Diff: 1.5, Sum: 28.7]
[Code Root Scanning (ms): Min: 0.4, Avg: 1.2, Max: 2.0, Diff: 1.5, Sum: 2.4]
[Object Copy (ms): Min: 17.5, Avg: 17.7, Max: 17.8, Diff: 0.3, Sum: 35.4]
[Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 2]
[GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
[GC Worker Total (ms): Min: 51.6, Avg: 51.7, Max: 51.8, Diff: 0.2, Sum: 103.4]
[GC Worker End (ms): Min: 73278093.6, Avg: 73278093.6, Max: 73278093.6, Diff: 0.0]
[Code Root Fixup: 0.7 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.4 ms]
[Other: 2.9 ms]
[Choose CSet: 0.6 ms]
[Ref Proc: 0.3 ms]
[Ref Enq: 0.0 ms]
[Redirty Cards: 0.3 ms]
[Humongous Register: 0.1 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.9 ms]
[Eden: 95.0M(95.0M)->0.0B(1223.0M) Survivors: 7168.0K->5120.0K Heap: 512.0M(2048.0M)->363.5M(2048.0M)]
[Times: user=0.11 sys=0.00, real=0.06 secs]
2016-09-28T10:40:00.815+0000: 73288.384: [GC pause (G1 Evacuation Pause) (young)
Desired survivor size 80740352 bytes, new threshold 15 (max 15)
- age 1: 1096960 bytes, 1096960 total
- age 2: 220208 bytes, 1317168 total
- age 3: 349352 bytes, 1666520 total
- age 4: 3325200 bytes, 4991720 tota
在下面的图片中,您可以看到问题 session 根源的路径,并且您可以看到只存在弱引用链。
请帮忙。或者至少给出一些建议。
最佳答案
正如 Holger 在评论中指出的那样,以下内容是错误的。我暂时将其保留在这里,以免其他人走上这条错误的道路。
无论如何,我建议摆脱可变的 hashCode
和整个 MEMORY_SESSION_MANAGER
(至少,更改 userId
在使用 session 作为 key 之前)。
Mutable hashCode
... 这很糟糕,但可以接受,只要它在使用后 永远不会改变。然而我能看见
Session session = new Session();
MEMORY_SESSION_MANAGER.addSession(session);
session.setUserId(userId);
你把它放在一个 HashMap
中,并立即更改 hashCode
。现在,行为未定义, map 可以在任何访问时抛出或执行无限循环。
如果是 C/C++,它也会吃掉你的猫。
真正发生的是 key 再也找不到了。所以它不能被删除,不是 .remove(key)
和
probably
也不在清理中。找不到,所以无法删除。 That's it. .使用错误的 hashCode
会搜索错误的槽。
As result after collection of all strong references on Session object it must be removed from WeakHashMap.
它必须只有在你遵守契约(Contract)的情况下才遵守契约(Contract)。而你没有。
关于java - 弱引用。当只剩下 WeakReferences 时,对象不会被删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39764809/
我一直在尝试编写我自己的弱/强指针,但我并不清楚其中的关系。我似乎遇到的所有事情都没有说清楚,而且一个医生经常会反驳另一个医生所说的话。任何人都可以详细解释弱/强指针关系,也许还有图像或代码示例吗?
静态/动态和强/弱类型之间有什么区别? 最佳答案 静态/动态类型涉及何时获取类型信息(在编译时或运行时) 强/弱类型是关于如何严格区分类型(例如,语言是否尝试从字符串到数字进行隐式转换)。 请参阅wi
我有一个非常奇怪的情况。我的服务器当前已关闭并收到 503 http 状态代码。基于如下给定的代码,代码进入 if 条件,但是当我将调试点置于 let error = self?.decodeErro
对于短期运行的操作,避免[weak self]是否可以接受?例如,URLSession 将保留 dataTask(with:completion:) 的闭包: final class ViewCont
我有一个非常奇怪的情况。我的服务器当前已关闭并收到 503 http 状态代码。基于如下给定的代码,代码进入 if 条件,但是当我将调试点置于 let error = self?.decodeErro
假设我有以下情况: Test1.java import java.lang.ref.WeakReference; public class Test1 { public WeakReferen
有没有办法告诉模拟器(我正在使用 Modelsim)当信号不是由任一双向接口(interface)驱动时将信号拉到弱“H”? 例如,如果我有一个 I2C 信号 I2C_SDA 被声明为来自 2 个模块
这是将一些值放入 WeakHashMap 中然后从映射中删除这些值的代码片段。它如何处理分配的内存? import java.util.*; public class WeakHashMap_Main
我正在尝试弄清楚智能指针可以实现什么。 但有一些感觉像是障碍。 普通指针有一个简短的定义 Someclass *p但是智能指针有点长shared_ptr p当您必须处理这些指针的模板(如 vector
这两行代码有区别吗? __weak IBOutlet UITextField *usernameField; @property (weak) IBOutlet UITextField *userna
我最近发现了 WeakHashMap Java 中的数据结构。 但是,我不明白它在不再正常使用时对映射进行垃圾收集是什么意思。数据结构如何知道我将不再在我的程序中使用 key ?如果长时间不引用 ke
我的问题是为什么 weak IBOutletCollection 总是 nil?如果将弱变强,我所有的按钮都在那里,这真的很奇怪。我试图理解苹果的逻辑,我看不出单个按钮和一组按钮在内存管理方面没有区别
我创建一个 WeakHashMap 为 WeakHashMap map = new WeakHashMap(); map.put(emp,"hello"); 其中 emp 是一个 Employee 对
在delphi sydney中,在对象(不是接口(interface))前面设置[weak]会受到惩罚吗?示例: TMyObject = class(Tobject) Private
在delphi sydney中,在对象(不是接口(interface))前面设置[weak]会受到惩罚吗?示例: TMyObject = class(Tobject) Private
众所周知,我们将声明一个可以打破强引用循环的弱委托(delegate)对象: // MyObject.h ... @property (nonatomic, weak) id delegate; ..
我已阅读this article关于Java中不同类型的引用(强引用、软引用、弱引用、幻像引用),但我不太理解。 这些引用类型之间有什么区别?每种类型何时使用? 最佳答案 Java 提供了两种不同类型
我突然想到...我相信弱引用的生命 与该引用的范围(在函数内或全局内)相关。 所以我想知道,只要我将数据处理保持在特定范围内,那么我应该可以使用 weak 与 strong 引用。正确的? 我问的原因
func addAdditionalElement(_ additionalSelectedElementsIDs: [String], startX: CGFloat, containerView:
我想要一个指针,以便我可以判断引用计数何时为 1。本质上,指针的工作方式类似于 weak_ptr,但清理工作需要手动进行。也就是说,程序每隔一段时间就会经历一个指针循环,并检查哪些指针只剩下一个引用。
我是一名优秀的程序员,十分优秀!