JMS is designed for high performance. In particular its design is such that you are meant to create a number of objects up front on the startup of your application and then resuse them throughout your application. e.g. its a good idea to create upfront and then reuse the following
The reason is that each create & destroy of the above objects typically requires an individual request & response with the JMS broker to ensure it worked. e.g. creating a connection, session, producer, then sending a message, then closing everything down again - could result in 7 request-responses with the server!
Note a little trick - you can reuse the same MessageProducer for sending messages to different destinations; just create it with a null destination and specify it on the send method.
Java Connector Architecture supports the pooling of JMS connections, sessions and MessageListeners, parallel message processing, thread pooling and transaction & exception handling, through the use of a JCA Resource Adapter.
Typically JCA is used in a J2EE container via MDBs; though there is a POJO Spring based JCA Container you can use, which is simple and lightweight and easy to embed inside Tomcat or any J2SE application.