First issue:
OpendesktopMimeDetector defines this:
private static String mimeCacheFile = "/usr/share/mime/mime.cache";
private static String internalMimeCacheFile = "src/main/resources/mime.cache";
The first references a file on the developer's machine. The second, I guess, is supposed to reference a file in the build structure. So we end up having to pull the actual mime.cache file from the JAR and put it into a temporary file. Then when we create OpendesktopMimeDetector, we have to reference the temporary file. Correct behavior should be that OpenDesktopMimeDetector pulls the mime.cache resource from the JAR by default.
Second issue:
If you create a single instance of OpenDesktopMimeDetector and use it repeatedly, you eventually get an error that looks something like this.
java.lang.IllegalArgumentException:
at java.nio.Buffer.position(Buffer.java:218)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.getString(OpendesktopMimeDetector.java:699)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.getString(OpendesktopMimeDetector.java:676)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.getMimeType(OpendesktopMimeDetector.java:672)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.lookupGlobNodeSuffix(OpendesktopMimeDetector.java:511)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.lookupGlobNodeSuffix(OpendesktopMimeDetector.java:496)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.lookupGlobNodeSuffix(OpendesktopMimeDetector.java:496)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.lookupGlobNodeSuffix(OpendesktopMimeDetector.java:496)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.lookupGlobSuffix(OpendesktopMimeDetector.java:466)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.lookupMimeTypesForGlobFileName(OpendesktopMimeDetector.java:449)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.getMimeTypesFileName(OpendesktopMimeDetector.java:160)
at eu.medsea.mimeutil.detector.OpendesktopMimeDetector.getMimeTypesFile(OpendesktopMimeDetector.java:192)
at eu.medsea.mimeutil.detector.MimeDetector.getMimeTypes(MimeDetector.java:53)
Apparently, it keeps reading from my temporary file and the pointers get messed up. I will let someone more knowledgeable than me dig into the code here and suggest a fix. I just thought you'd like to know that there's a problem with using OpendesktopMimeDetector as a singleton.
So, I create a new instance of OpendesktopMimeDetector each time I need it. This leads to my third issue.
Third issue:
OpendesktopMimeDetector creates a Timer. It passes a Thread to the timer. This Thread is an inner class of OpendesktopMimeDetector, so it holds a pointer to it.
* The contained Timer holds the Thread in a wait state. The Thread exists until the Timer goes away.
* The Thread contains a reference to the OpendesktopMimeDetector. So it can't be GC'd.
* The Timer is contained in OpendesktopMimeDetector, so it can't go away.
The result of this is that every time I create a new OpendesktopMimeDetector, I leak a thread. I also leak a few objects that can't be GC'd, but it only takes a few thousand zombie threads to crash me. Can you guess how long it takes my app server to crash with an OOM error? :-)
The workaround I found is:
* Create a new instance of OpendesktopMimeDetector each time I need one, since I can't rely on a singleton to work reliably.
* When I am done with it, I reflectively grab the private Timer field, cancel it, purge it, and set it to null.
At this point, the Java GC will take care of tearing down the objects, and the Timer threads are no longer being leaked.
We have exactly the same issues.