Java WeakReferences =理解问题(使用HornetQ JMS实现)?

时间:2011-08-11 16:21:41

标签: java jms weak-references hornetq

以下代码不起作用:

原因:

我认为我追查原因是: http://community.jboss.org/thread/150988 =>本文说HornetQ使用弱引用

我的问题: 为什么代码不运行? (我的代码运行时略有不同,但代码重复失败)。我的唯一猜测是,那个 以下参考:

private Connection connection = null;
private Session session = null;
private MessageProducer producer = null;

不被视为强有力的参考? (这导致了垃圾收集器移除了对象的事实......但是它们不是强有力的参考吗?

或者代码是否存在另一个问题(如上所述,如果我将所有内容复制到一个单独的方法中,代码运行正常。但如果我在下面使用Singleton方法代码不起作用...)另一个假设是它可能与ThreadLocal有关,但我只使用一个线程...

代码无法正常工作(已拆除):

public class JMSMessageSenderTest {
    private static final Logger logger = Logger.getLogger(JMSMessageSenderTest.class);

    private static JMSMessageSenderTest instance;

    private Connection connection = null;
    private Session session = null;
    private MessageProducer producer = null;

    private JMSMessageSenderTest() {
        super();
    }


    public static JMSMessageSenderTest getInstance() throws JMSException {
        if (instance==null) {
            synchronized(JMSMessageSenderTest.class) {
                if (instance==null) {
                    JMSMessageSenderTest instanceTmp = new JMSMessageSenderTest();
                    instanceTmp.initializeJMSConnectionFactory();
                    instance = instanceTmp;
                }
    } }
        return instance;
    }


    private void createConnectionSessionQueueProducer() throws Exception {

        try {


            Queue queue = HornetQJMSClient.createQueue("testQueue");

            connection = initializeJMSConnectionFactory();

             session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

             producer = session.createProducer(queue);

             connection.start();

        } catch (Exception e) { 
            cleanupAfterError();
            throw e;
        }

    }


    private void cleanupAfterError() {

        if (connection != null){
             try{
                 connection.close();
             }catch(JMSException jmse) {
                 logger.error("Closing JMS Connection Failed",jmse);
             }
         }
    session = null;
    producer = null;

    }


    public synchronized void sendRequest(String url) throws Exception {

            if (connection==null) {
                createConnectionSessionQueueProducer();
            }

        try {

             //HERE THE EXCEPTION IS THROWN, at least when debugging
             TextMessage textMessage = session.createTextMessage(url);

             producer.send(textMessage); 

            } catch (Exception e) {
            cleanupAfterError();
            throw e;
        }

    }

        private Connection initializeJMSConnectionFactory() throws JMSException{

        Configuration configuration = ConfigurationFactory.getConfiguration(null, null);

        Map<String, Object> connectionParams = new HashMap<String, Object>();

        connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5445);
        connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.HOST_PROP_NAME, "localhost");

        TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName(), connectionParams);

        ConnectionFactory connectionFactory = (ConnectionFactory) HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);

    //      return  connectionFactory.createConnection(login, password);    
        return connectionFactory.createConnection();

    }


    /**
     * Orderly shutdown of all resources.
     */
    public void shutdown() {
        cleanupAfterError();
    }


}

TestCode运行上面的代码

JMSMessageSenderTest jmsMessageSender = JMSMessageSenderTest.getInstance();
jmsMessageSender.sendRequest("www.example.com)");
jmsMessageSender.shutdown();

出现以下错误:

I'm closing a JMS connection you left open. Please make sure you close all JMS connections explicitly before letting them go out of scope!
The JMS connection you didn't close was created here:
java.lang.Exception
    at org.hornetq.jms.client.HornetQConnection.<init>(HornetQConnection.java:152)
    at org.hornetq.jms.client.HornetQConnectionFactory.createConnectionInternal(HornetQConnectionFactory.java:662)
    at org.hornetq.jms.client.HornetQConnectionFactory.createConnection(HornetQConnectionFactory.java:121)

解决方案:

1。)你还必须保持对ConnectionFactory的引用(参见下面Clebert的答案)

private ConnectionFactory factory = null;

2。)此代码包含一个严重的隐藏错误(不容易发现): 我在构造函数和createConnectionSessionQueueProducer()方法中初始化了Connection。因此它将覆盖旧值并且(因为它是需要关闭的Ressource)将导致HornetQ然后将关闭的陈旧连接,然后将抛出错误。

非常感谢!马库斯

2 个答案:

答案 0 :(得分:2)

HornetQ将在连接工厂发布时关闭连接工厂。

您需要保留连接工厂的参考。

答案 1 :(得分:1)

我也有类似的问题。但它不应该崩溃。你的实现看起来不错。但唯一的问题是你没有关闭JMS连接,而jMS连接又被hornetQ gc关闭了。

代码可能出错的一点是你只在异常后才调用cleanupAfterError()。在发布消息并且JMS连接处于空闲状态之后,您也应该调用相同的方法。由于您只是打开一个连接来发布消息,然后不关闭该连接,除非发生异常,Hornetq GC正在找到该对象并在抛出此错误时将其删除。

如果我错过了某些内容,请告诉我