【问题标题】:Reference to session attrribute not getting null despite explicitly setting it to null尽管将会话属性显式设置为 null,但对会话属性的引用仍不为 null
【发布时间】:2013-07-23 12:04:50
【问题描述】:

我有一个对象存储在会话中。在我的控制器中,当用户发送请求时,它同时执行以下代码:

MyObject obj = (MyObject) req.getSession().getAttribute("myObject");
while(!obj.isNewResultAvailable()){
    //will loop until new result is available.
}

正如我所指出的,它是并发执行的,因此当控件仍在循环中时,用户可以做一些其他事情,例如,当用户按下另一个按钮时,将向执行以下操作的控制器发送请求以下:

MyObject obj = (MyObject) req.getSession().getAttribute("myObject");
obj = null;

我的期望是,循环直到有新结果可用的代码将抛出NullPointerException。才发现我们不是。

那么,为什么从另一个控制器的会话中提取的对象不是null,尽管将该对象设置为另一个控制器为null

编辑:

在我当前的代码中,我实际上尝试过这样做

req.getSession().setAttribute("myObject", null);

req.getSession().removeAttribute("myObject");

不过,这并没有解决我的问题,while 循环中的对象仍然没有为空。

实现

对于那些会遇到这种困惑的人来说,我的问题的根源是我对 Java 中对象的传递方式感到困惑。我的问题很简单,obj = null 只是将objreference 设置为 null 而 NOT 对象本身。

正如 morgano 所指出的,会话中的对象已被执行 while 循环的线程本地引用,因此,req.getSession().setAttribute("myObject", null);req.getSession().removeAttribute("myObject"); 不会导致对象为空。这些只是基本上从会话中删除对对象的引用(因此理想情况下使其成为 gc 的候选者,这在我的情况下不会发生,因为该对象是由长时间运行的 http 请求本地引用的 [the while loop thing]) .

【问题讨论】:

  • 你能发布一些你的并发控制器代码吗?
  • 能否请投反对票的人解释为什么投反对票?

标签: java httpsession


【解决方案1】:

不要那样做,这样做:

req.getSession().setAttribute("myObject", null);

或者更好:

req.getSession().removeAttribute("myObject");

你正在做的事情是将一个对象的引用设置为空,你根本没有修改会话属性。

问题版后更新:

一旦“迭代”线程引用了您的对象,“删除”线程将其从会话中删除是徒劳的,您的对象已被第一个线程中的局部变量引用。

【讨论】:

    【解决方案2】:

    考虑这个例子:

    MyObject a = new MyObject();
    MyObject b = a;
    b = null;
    

    你似乎期待的是:

    MyObject a = new MyObject(); // a is the new object
    MyObject b = a; // b is the same object
    b = null; // set the object referenced by both a and b to null
    

    真正发生的事情:

    MyObject a = new MyObject(); // a is the new object
    MyObject b = a; // b points to the same object as a
    b = null; // b doesn't point to anything
    

    简而言之:不是将 referenced value 设置为 null(即示例中的会话),而是将 reference 本身 设置为 null(即obj 在您的示例中)。

    【讨论】:

    • 我的问题是在 Java 中。你能用 Java 上下文更新你的答案吗?
    • 完成。除了 MyObject 位之外,它基本上是相同的。
    【解决方案3】:

    做这样的事情。会话是一个键值映射。您必须针对特定的键值显式设置 null。

    req.getSession().setAttribute("myObject", null);
    

    或完全删除密钥。

    req.getSession().removeAttribute("myObject");
    

    【讨论】:

    • 我做到了,但对象并没有被清空
    猜你喜欢
    • 2012-11-25
    • 1970-01-01
    • 2018-09-02
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 2021-09-06
    相关资源
    最近更新 更多