【问题标题】:Java Object returning to default valuesJava 对象返回默认值
【发布时间】:2013-03-03 00:42:21
【问题描述】:

我有以下代码结构。

Transaction 类型的事务处理程序,它是客户端处理程序类中的一个字段,它与服务器通信。 (客户端处理程序和服务器并置),客户端通过序列化对象消息与客户端处理程序对话。

当一个新的事务请求来自客户端时,(使用对象输入流的 readObject() 方法进入线程),然后我执行一系列 trx_handler.setFoo(trx.getFoo)))。这很好用,我可以处理第一个请求。但是当后续请求进来时(由于循环结构,它仅在第一个请求完成后才开始执行,我发现 trx 处理程序已重新初始化为其默认值,对象仍然存在,但里面的所有值都是默认的。什么会导致这个问题?

我的第一个猜测是垃圾回收,但在我的客户端处理程序类中,总是有一个指向这个 trx_handler 的指针。

下面的代码说明了会发生什么。语句首先是 start 类型,因此 trx_handler 将被正确初始化。然后将调用handle_statement。随后应该会收到后续语句,但此时 trx_handler 已重新初始化为其默认设置,因此 access_set 字段为空,会话 id 也是如此,并且对 hande_statement 中的对象所做的修改均不可见

谢谢

  public class Handler { 

  private Statement trx_handler; 

 /* Constructor initialises trx_handler to new Statement(); */

 public ClientHandler(final Socket socket, long uid, Server server, ObjectInputStream ois) throws           IOException, Exception {
 LOGGER.info("Constructing Handler");
 this.uid = uid;
 this.server = server;
 this.socket = socket;
 this.database = server.getDB();
 this.trx_sys = database.getTransactionManager();
 create_listening(socket, ois);
 out = socket.getOutputStream();
 oos = new ObjectOutputStream(out);
 this.trx_handler = new Statement(false);

}

  private void create_incoming(final Socket socket, final ObjectInputStream stream) {
  Thread incoming = new Thread() {
  @Override
  public void run() {
    ObjectInputStream ois = stream;
    InputStream in = null;
    while (true) {
      Object statement = null;

      try {

        statement = ois.readObject();
        execute_stat(statement, socket, null);
        LOGGER.info("Ready to execute next "); 
      } catch (SocketException e) {
        LOGGER.severe("Connection Closed");
        return;
      } catch (IOException e) {
        LOGGER.severe("Connection Closed");
        return;
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (Exception e) {
        e.printStackTrace();
        String error_message = e.getMessage();
        send_error(socket, error_message);
      }

    }
  }
};
incoming.setDaemon(true);
incoming.start();

}

 private synchronized void execute_stat(Statement trx) {
  if (trx.getTransactionState() == Consts.trx_end) {
    trx_sys.commitTransaction(trx_handler);
    return;
  } else if (trx.getTransactionState() == Consts.trx_start) {
   try {
    trx_handler.setAccessSet(trx.getAccessSet());
    trx_handler.setSession_id(trx.getSession_id());
    trx_sys.startTransaction(trx_handler);
    handle_statement(socket, trx_handler);


    /* TEST HERE THAT FIELDS IN TRX_HANDLER ARE CORRECTLY SET (INCLUDING SOME MODIFIED IN       
    handle_statement and they are correctly set */

  return;
  } catch (Exception ex) {
    Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex);
  }
}
try {
  LOGGER.info("Execute Trx: stat");

  /* Can't see modifications made in the start case */ 
  Statement stats = trx.getStatement();
  trx_handler.setStatement(stats);
  handle_statement(stats, socket, trx_handler);

} catch (Exception e) {
  e.printStackTrace();

}

return;
}

【问题讨论】:

  • 这与垃圾回收无关,很可能是您代码中的错误。我认为我们无法根据目前提供的信息来猜测错误是什么。考虑进行更多调试,然后发布更多相关代码和信息。
  • (已更新以添加更详细的代码)

标签: java sockets serialization


【解决方案1】:

您需要为每笔交易发送一个全新的对象,使用ObjectOutputStream.writeUnshared(),或者在发送之间调用ObjectOutputStream.reset()

【讨论】:

  • 问题不在于我通过输出流发送的对象(例如,我已经在使用重置),而是客户端处理程序中的字段对象,出于某种原因,这似乎在两个句柄语句调用之间重新初始化为默认字段值。
  • @user1018513 真的吗?你读过Javadoc吗?您是否知道,如果您第二次发送具有不同值的同一对象两次,您将不会收到更改后的值?您是否尝试过这些建议?
  • 是的,并实现了它们。我在对象流中收到的 Statement 对象包含正确的值。重置的是 trx 处理程序。
  • 您没有显示实例化类 Handler 的方式/位置,这可能是问题所在。
  • 所以你的代码中有一个错误,你没有发布的部分。猜测垃圾收集或其他神奇地重置您的字段只是抓住稻草。
猜你喜欢
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 2016-04-08
  • 2017-09-02
相关资源
最近更新 更多