StringWriter sw = new StringWriter(); JAXBContext jaxbContext = JAXBContext.newInstance(myObject.getClass()); Marshaller marshal = jaxbContext.createMarshaller(); marshal.marshal(myObject, sw);
The unfortunate thing is that this is exactly what one would come up with after skimming the examples in the javadoc.
The recommended solution on the internets is to cache the JAXBContext, including re-using it on multiple threads. This is a bit novel as the documentation for the JAXBContext doesn't indicate this will happen and it also doesn't indicate the JAXBContext is thread-safe. To discover that you have to go into specific implementation information, such as https://jaxb.dev.java.net/guide/Performance_and_thread_safety.html.
These details vary by implementation so one might legitimately argue the javase documentation is correct. It's really just aggravating to discover that the implementation is built in a way so likely to cause clients to leak. This strikes me as a great example of a very bad implementation of an API, especially given that the implementation could easily maintain a lookup and avoid re-creating the dynamic classes and creating the leak for us.