Well, i add this for reference to other people wondering if they need to abandon JAXB.
Adding
-Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
did the job. The performance now has the same order of magnitude. It seems we have a plain classpath issue. On the large classpath, the service provider lookup needed for the (uncached) DocumentBuilderFactory was the key factor to the bad performance. Give the VM a known implementation to avoid searching....
I tried this after "stochastical" profiling (press suspend whenever you like :-) always ended up in the search sequence like this:
Thread [main] (Suspended)
owns: VirtualKeyStoreHolder (id=417)
owns: CertificateStoreEnvironment (id=418)
owns: ManagedCertificateProvider (id=419)
owns: CertificateStoreEnvironment$1 (id=420)
WinNTFileSystem.getBooleanAttributes(File) line: not available [native method]
File.exists() line: 733
URLClassPath$FileLoader.getResource(String, boolean) line: 999
URLClassPath$FileLoader.findResource(String, boolean) line: 966
URLClassPath.findResource(String, boolean) line: 146
URLClassLoader$2.run() line: 385
AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]
Launcher$AppClassLoader(URLClassLoader).findResource(String) line: 382
Launcher$AppClassLoader(ClassLoader).getResource(String) line: 1003
Launcher$AppClassLoader(ClassLoader).getResourceAsStream(String) line: 1193
SecuritySupport$4.run() line: 96
AccessController.doPrivileged(PrivilegedAction<T>) line: not available [native method]
SecuritySupport.getResourceAsStream(ClassLoader, String) line: 89
FactoryFinder.findJarServiceProvider(String) line: 250
FactoryFinder.find(String, String) line: 223
DocumentBuilderFactory.newInstance() line: 123
TransformerIdentityImpl.createResultContentHandler(Result) line: 215
TransformerIdentityImpl.setDocumentLocator(Locator) line: 881
DomLoader$State.<init>(DomLoader, UnmarshallingContext) line: 78
DomLoader<ResultT>.startElement(UnmarshallingContext$State, TagName) line: 113
XsiTypeLoader.startElement(UnmarshallingContext$State, TagName) line: 76
UnmarshallingContext._startElement(TagName) line: 481
UnmarshallingContext.startElement(TagName) line: 459
SAXConnector.startElement(String, String, String, Attributes) line: 148
SAXParserImpl$JAXPSAXParser(AbstractSAXParser).startElement(QName, XMLAttributes, Augmentations) line: 501
XMLNSDocumentScannerImpl.scanStartElement() line: 400
XMLNSDocumentScannerImpl$NSContentDriver(XMLDocumentFragmentScannerImpl$FragmentContentDriver).next() line: 2755
XMLNSDocumentScannerImpl(XMLDocumentScannerImpl).next() line: 648
XMLNSDocumentScannerImpl.next() line: 140
XMLNSDocumentScannerImpl(XMLDocumentFragmentScannerImpl).scanDocument(boolean) line: 511
XIncludeAwareParserConfiguration(XML11Configuration).parse(boolean) line: 808
XIncludeAwareParserConfiguration(XML11Configuration).parse(XMLInputSource) line: 737
SAXParserImpl$JAXPSAXParser(XMLParser).parse(XMLInputSource) line: 119
SAXParserImpl$JAXPSAXParser(AbstractSAXParser).parse(InputSource) line: 1205
SAXParserImpl$JAXPSAXParser.parse(InputSource) line: 522
UnmarshallerImpl.unmarshal0(XMLReader, InputSource, JaxBeanInfo) line: 211
UnmarshallerImpl.unmarshal(XMLReader, InputSource) line: 184
UnmarshallerImpl(AbstractUnmarshallerImpl).unmarshal(InputSource) line: 137
UnmarshallerImpl(AbstractUnmarshallerImpl).unmarshal(InputStream) line: 184
VirtualKeyStoreTools.createVirtualKeyStore(InputStream) line: 54
... more to come
As there's a pending bounty, i'll offer this to @Osw (when the bounty can be applied) as the answer "Yes, you can JAXB" is correct. I think minor performance differences do no justify using a plan SAX solution or staying any longer with the digester. In addition, caching the JAXBContext seems wise, i can not tell about caching the unmarshaller context - maybe someone adds information about this.
Thank's for your support.
EDIT
As requested by @Osw here are some (disappointing) figures for the resulting overall performance.
I did some dirty instrumentation for the old and the new application directly around the parsing. While the figures are "acceptable" for an interactive application loading a bunch of files, i must admit that the digester is still more than 2* faster.
- Digester based, ~1 MB file containing 4000 generic entries = 400ms
- JAXB based, see above, 900ms
The JAXB implementation already contains a cache for the unmarshaller, so the "out of the box" optimizations are done. This leaves me with an functional application that urgently needs some more profiling. I will come back when this is done and some interesting tricks of general interest will pop up.