Extraction directory problem with WebStart/Firefox

It looks like jME3 may be trying to extract the native libraries to silly directories (specifically the read-only Program Files directory) when deploying using WebStart under Webstart/Firefox on Windows 7.



Shouldn’t the last choice should be the java temp.dir, which is pretty much guaranteed to be writeable?



Report from user follows. Same user has no problem under Chrome/7.


Java Web Start 1.6.0_24
Using JRE version 1.6.0_24-b07 Java HotSpot(TM) Client VM
User home directory = C:\Users\Nick_2
c: clear console window
f: finalize objects on finalization queue
g: garbage collect
h: display this help message
m: print memory usage
o: trigger logging
p: reload proxy configuration
q: hide console
r: reload policy configuration
s: dump system and deployment properties
t: dump thread list
v: dump thread stack
0-5: set trace level to
Loaded resource ICON_256x256 -> BufferedImage@1afae45: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@da4b71 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 256 height = 256 #numDataElements 4 dataOff[0] = 3
Loaded resource ICON_128x128 -> BufferedImage@55e55f: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@da4b71 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 128 height = 128 #numDataElements 4 dataOff[0] = 3
Loaded resource ICON_32x32 -> BufferedImage@2c1e6b: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@da4b71 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 32 height = 32 #numDataElements 4 dataOff[0] = 3
Loaded resource ICON_16x16 -> BufferedImage@3bc257: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@da4b71 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 16 height = 16 #numDataElements 4 dataOff[0] = 3
Feb 27, 2011 4:18:33 PM com.jme3.system.JmeSystem initialize
INFO: Running on jMonkey Engine 3 Alpha 0.6
Feb 27, 2011 4:18:33 PM com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory #1: http://www.davidc.net/sites/default/wiseup/
Feb 27, 2011 4:18:33 PM com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory #2: C:\Program Files\Mozilla Firefox
Feb 27, 2011 4:18:33 PM com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory #3: C:\Program Files\Mozilla Firefox
Feb 27, 2011 4:18:33 PM com.jme3.system.JmeSystem initialize
SEVERE: Error while copying native libraries
java.io.FileNotFoundException: C:\Program Files\Mozilla Firefox\lwjgl.dll (Access is denied)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.(Unknown Source)
at java.io.FileOutputStream.(Unknown Source)
at com.jme3.system.Natives.extractNativeLib(Natives.java:74)
at com.jme3.system.Natives.extractNativeLibs(Natives.java:175)
at com.jme3.system.JmeSystem.initialize(JmeSystem.java:385)
at com.jme3.system.JmeSystem.newContext(JmeSystem.java:301)
at com.jme3.app.Application.start(Application.java:321)
at com.jme3.app.Application.start(Application.java:304)
at com.jme3.app.SimpleApplication.start(SimpleApplication.java:126)
at net.davidc.egp.wiseup.WiseUpMain.main(WiseUpMain.java:470)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javaws.Launcher.executeApplication(Unknown Source)
at com.sun.javaws.Launcher.executeMainClass(Unknown Source)
at com.sun.javaws.Launcher.doLaunchApp(Unknown Source)
at com.sun.javaws.Launcher.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Exception in thread "LWJGL Renderer Thread" java.lang.UnsatisfiedLinkError: Can't load library: C:\Program Files\Mozilla Firefox\lwjgl.dll
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at org.lwjgl.Sys$1.run(Sys.java:69)
at java.security.AccessController.doPrivileged(Native Method)
at org.lwjgl.Sys.doLoadLibrary(Sys.java:65)
at org.lwjgl.Sys.loadLibrary(Sys.java:81)
at org.lwjgl.Sys.(Sys.java:98)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:192)
at java.lang.Thread.run(Unknown Source)


-davidc
1 Like

OK I can’t figure out how to get the forum to display backslash characters (neither <pre> nor backslash-backslash work), but in the above log, the c-program files etc things really do have backslashes in the path.



-davidc

This seems to be a common issue to Firefox, as I have six Firefox users reporting the same problem now. I guess they are doing some magic to run jnlp files internally rather than just executing javaws.exe with the file? Or maybe javaws.exe is executed with the current directory of the Firefox process?



-davidc

Using Firefox, choosing to either “Open” the jnlp file, or to “Save” and then run it from the Downloads window, results in:



[java]INFO: Extraction Directory #1: http://www.davidc.net/sites/default/wiseup/

02-Mar-2011 18:05:03 com.jme3.system.Natives extractNativeLibs

INFO: Extraction Directory #2: C:Program FilesMozilla Firefox

02-Mar-2011 18:05:03 com.jme3.system.Natives extractNativeLibs

INFO: Extraction Directory #3: C:Program FilesMozilla Firefox

02-Mar-2011 18:05:03 com.jme3.system.JmeSystem initialize

[/java]



None of which are writeable.



However, looking through the Natives class, it looks like the first and third directories are never actually used anyway. But even if they were, user.dir is the same as cwd and thus the Firefox directory.



Any objection to my rewriting this class to test in order and use the first writeable directory out of:



getExtractionDir()

{user.dir}

{user.home}/.jme3

{java.io.tmpdir}/jme3



-davidc

Patch submitted: http://hub.jmonkeyengine.org/groups/contribution-depot-jme3/forum/topic/better-selection-of-natives-extraction-directory/

You’re not supposed to use native extraction in a restricted environment. First call the method “JmeSystem.setLowPermissions(false)” to disable native extraction.

Then, import the JNLP extension provided by LWJGL in your JNLP file.

I was going to write a wiki page to explain this, but I don’t have permission, so here it is:



When running under WebStart, jMonkeyEngine may not have permission to extract the native libraries to the current directory. To avoid this problem, you can instruct WebStart to load the native libraries itself using the JNLP file, and then instruct jME3 not to try to do so itself.

== Simple way ==

You can import the LWJGL JNLP extension directly into your extension, however be aware that your application will break whenever they update their jars. Simply add this line to your JNLP:

[java]<extension name="lwjgl" href="http://lwjgl.org/webstart/2.7.1/extension.jnlp" />[/java]

== Reliable way ==

=== Native jars ===

You can download the LWJGL native jars from their site, or to ensure you're using the exact same version as bundled with your jME3 release, make your own:

mkdir tmp
cd tmp
jar xfv ../jME3-lwjgl-natives.jar
cd native
for i in *; do
cd $i
jar cfv ../../native_$i.jar .
cd ..
done

Remember to sign all the jar files and move them into the right place from the tmp directory.

=== JNLP file ===

Add the following to your JNLP file:

[java] <resources os="Windows">
<j2se version="1.4+"/>
<nativelib href="native_windows.jar"/>
</resources>
<resources os="Linux">
<j2se version="1.4+"/>
<nativelib href="native_linux.jar"/>
</resources>
<resources os="Mac OS X">
<j2se version="1.4+"/>
<nativelib href="native_macosx.jar"/>
</resources>
<resources os="SunOS" arch="x86">
<j2se version="1.4+"/>
<nativelib href="native_solaris.jar"/>
</resources>[/java]

=== Set low-permissions mode ===

In your main() method, if running under WebStart, tell jME3 it is running in a low-permission environment so that it doesn't try to load the natives itself:

[java]
public static void main(String[] args)
{
if (System.getProperty("javawebstart.version") != null) {
JmeSystem.setLowPermissions(true);
}
[/java]

3 Likes
davidc said:
I was going to write a wiki page to explain this, but I don't have permission, so here it is:

Uh what? why? how? Did you do it like it says in the site manual? The edit link is in the top menu bar (the black one thats always visible).

Yes, I am dumb.

Thanks for the tutorial :slight_smile:

Hopefully in the future jMP will take care of the extension part