1

下面的代码不起作用:

原因:

我假设我找到了原因:http: //community.jboss.org/thread/150988 =>这篇文章说 HornetQ 使用了弱引用

我的问题: 为什么代码不运行?(我有这个代码运行略有不同的实现,但代码失败反复失败)。我唯一的猜测是,以下参考资料:

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

不算是强引用吗?(这导致垃圾收集器删除对象......但是它们不是强引用吗?

或者代码是否存在另一个问题(如我所说,如果我将所有内容复制到一个方法中,代码运行良好。但如果我使用下面的单例方法,则代码不起作用......)另一个假设是它可能必须这样做使用 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() 方法中初始化了连接。因此它将覆盖旧值并且(因为它是一个需要关闭的资源)将导致一个陈旧的连接,然后 HornetQ 将关闭并抛出错误。

非常非常感谢!马库斯

4

2 回答 2

2

当连接工厂被释放时,HornetQ 会关闭连接工厂。

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

于 2011-08-11T16:53:20.670 回答
1

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

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

如果我错过了什么,请告诉我

于 2011-08-11T16:33:34.010 回答