Question

I'm enhancing a client, which is part of a bigger project. Because of the lack of speed i was forced to switch to CNI and therefore i had to generate native code with the GNU-gcj compiler (gnu 4.6.3).

The compiling and linking works fine (thanks to the -findirect-dispatch flag) and i don't have any problems executing the output. But when it comes to the communication between the client and the server, the client immediately disconnects. The reason:

[XStreamClient Reader] WARN - Client disconnected (Exception: com.thoughtworks.xstream.io.StreamException: Cannot create XmlPullParser)

(This Exeption only appears in the gcj compiled version of the client. When i run the code with the java interpreter - things work well (but too slow^^)) --> The challenging part is that i can't retrieve the source code of where this exception occurs because it is in a pre-compiled (Java class files) library the client uses. (And I cannot contact the author of that library)

I guess the library invokes the XppReader which then tries to create a XmlPullParser class and fails.

I bind in the XStream (vers. 1.4.3) library (and other required *.jars) by unpacking them and compiling the created *.class files and then linking the object files. This seems to work for all other librarys, too. (My OS=Ubuntu)

What i already did to overcome this problem: I googled intensively for XStream/XmlPullParser and gcj and replaced the "xmlpull"- and "kxml2"-files with different versions. But nothing worked. Does anyone of you have a clue of what might be the solution?

EDIT:

I figured out that the reason why the XmlPullParser creation fails is that the META-INF directory with the /services/org.xmlpull.v1.XmlPullParserFactory file can not be found by the XmlPullParserFactory.newInstance function. This is due to the fact that i only compiled and linked the *.jar's *.class files. So as soon as i found i way to link the META-INF directory into the executable in away that the function can find and access it, the problem should be solved. Does anyone of you already know a way to do so?

Was it helpful?

Solution 3

As i already edited into my question, the reason why the creation fails is that the XmlPullParserFactory.newInstance method is not able to access the /META-INF/services/org.xmlpull.v1.XmlPullParserFactory file by using the following line of code:

InputStream is = context.getResourceAsStream (RESOURCE_NAME);

(RESOURCE_NAME equals "/META-INF/services/org.xmlpull.v1.XmlPullParserFactory")

I must admit that i didn't find a way to bind in the needed META-INF directory into the executable, which would have been one of the most elegant solutions. But since the XmlPullParserFactory.java file (and XStream library) is open source you just need do add one line of code into above's source file and replace the old class, with the new one - and that's it.

In the public static XmlPullParserFactory newInstance (String classNames, Class context) function the program only wants to read from the RESOURCE_NAME file when classNames == null. So what we do to avoid this is to assign the RESOURCE_NAME's file content to the classNames variable by our selves and for that place this line of code above the if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) statement:

classNames = "org.xmlpull.mxp1.MXParser,org.xmlpull.mxp1_serializer.MXSerializer";

"org.xmlpull.mxp1.MXParser,org.xmlpull.mxp1_serializer.MXSerializer" is my RESOURCE_NAME-file's content. If the content of your file differs from mine -> put in yours instead.

Best regards, Chris

OTHER TIPS

I think xmlpull need an implementation which can use xpp3 as its implementation. Please add following code into your pom.xml and if required, add these jar files to the software which requires them.

<dependency>
    <groupId>xmlpull</groupId>
    <artifactId>xmlpull</artifactId>
    <version>1.1.3.1</version>
</dependency>
<dependency>
    <groupId>xpp3</groupId>
    <artifactId>xpp3</artifactId>
    <version>1.1.3.3</version>
</dependency>

I think that you've made a couple of mistakes in your implementation platform choices:

  • You probably didn't need to go to the lengths of implementing stuff in native code "for speed". For most things you can get roughly comparable speed in Jana as in native code, especially if you take the time to profile and optimize your Java code.

  • Assuming that you did, CNI was a poor choice. You would have been better off using JNI or JNA, both of which allow you to use Oracle HotSpot / OpenJDK releases.

  • GCJ is a poor choice because (as you have observed) some things don't work, and debugging is more difficult. (See also Is GNU's Java Compiler (GCJ) dead?)

  • Relying on a library that you cannot get source code for is unfortunate.

My advice would be to revisit as many of those "missteps" as possible.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top