0

I'm having a huge problem with my java webstart application, I have tries a lot of solutions, but none seems to work correctly in th end.

I need to write a webstart applet to load basic hardware info about the client computer to check if my client can connect on our systems and use the software four our courses. I use Sigar to load the CPU and Memory information and then use JNI to load a custom c++ script that check the graphic card name (This one works perfectly).

I've put all my dlls in src/resources folder to load them in the jar, I also use what we call here "engines" which are classed that do specified operations (In our case, Jni Engine, Config Engine and Data Engine (Code below)), I'm new to webstart so I'm not sure if this concept works well with library loading.

I've tries to add the dlls in a jar as a library in Netbeans, I've tried to add the dlls in the jnlp, but each run recreates it and I can't add them with project properties, finnaly, I've built my Data Engine in a way that should load the dlls in the java temp directory in case they are not there, but Sigar still don't want to work. I've also put my dll in the java.library.path correctly cofigured (As it works in local).

It work when I run my main class locally (With right click-run), but when I click the run button to load the webstart, it crashes with this error message (it happens in ConfigEngine as it extends SigarBase) :

JNLPClassLoader: Finding library sigar-amd64-winnt.dll.dll no sigar-amd64-winnt.dll in java.library.path org.hyperic.sigar.SigarException: no sigar-amd64-winnt.dll in java.library.path

Here's the code :

JNi Engine (Loads the c++ code for the graphic card)

package Engine;
public class JniEngine
{
    static private final String nomLibJni = "JniEngine";
    static private final String nomLibJni64 = "JniEngine_x64";

    static
    {
        if (System.getProperty("os.arch").contains("86"))
        {
            System.loadLibrary(nomLibJni);
        }
        else
        {
            System.loadLibrary(nomLibJni64);
        }
    }

    public native String getInfoGPU() throws Error;
}

ConfigEngine

package Engine;

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.cmd.SigarCommandBase;

public class ConfigEngine extends SigarCommandBase
{
    private final String nomOsAcceptes = "Windows";

    static
    {
        DataEngine data;
    }

    public ConfigEngine()
    {
        super();
    }

    @Override
    public void output(String[] args) throws SigarException
    {
    }

    public HashMap<String, String> getMap() throws SigarException, SocketException
    {
        HashMap<String, String> hmConfig = new HashMap<>();
        loadInfoCpu(hmConfig);
        loadInfoRam(hmConfig);
        loadInfoOs(hmConfig);
        loadInfoNet(hmConfig);
        loadInfoGpu(hmConfig);
        return hmConfig;
    }

    private void loadInfoCpu(HashMap<String,String> Hashmap) throws SigarException
    {
        org.hyperic.sigar.CpuInfo[] configCpu = this.sigar.getCpuInfoList();
        org.hyperic.sigar.CpuInfo infoCpu = configCpu[0];
        long cacheSize = infoCpu.getCacheSize();
        Hashmap.put("Builder", infoCpu.getVendor());
        Hashmap.put("Model" , infoCpu.getModel());
        Hashmap.put("Mhz", String.valueOf(infoCpu.getMhz()));
        Hashmap.put("Cpus nbr", String.valueOf(infoCpu.getTotalCores()));
        if ((infoCpu.getTotalCores() != infoCpu.getTotalSockets()) || 
                (infoCpu.getCoresPerSocket() > infoCpu.getTotalCores()))
        {
            Hashmap.put("Cpus", String.valueOf(infoCpu.getTotalSockets()));
            Hashmap.put("Core", String.valueOf(infoCpu.getCoresPerSocket()));
        }
        if (cacheSize != Sigar.FIELD_NOTIMPL) {
            Hashmap.put("Cache", String.valueOf(cacheSize));
        }
    }

    private void loadInfoRam(HashMap<String,String> Hashmap) throws SigarException
    {
        org.hyperic.sigar.Mem mem = this.sigar.getMem();
        Hashmap.put("RAM" , String.valueOf(mem.getRam()));
        Hashmap.put("Memoery", String.valueOf(mem.getTotal()));
        Hashmap.put("Free", String.valueOf(mem.getUsed()));
    }

    private void loadInfoOs(HashMap<String,String> Hashmap) throws SigarException
    {
        Hashmap.put("OS", System.getProperty("os.name"));
        Hashmap.put("Version", System.getProperty("os.version"));
        Hashmap.put("Arch", System.getProperty("os.arch"));
    }

    private void loadInfoNet(HashMap<String,String> Hashmap) throws SocketException
    {
        List<NetworkInterface> interfaces = Collections.
                                    list(NetworkInterface.getNetworkInterfaces());
        int i = 1;
        for (NetworkInterface net : interfaces)
        {
            if (!net.isVirtual() && net.isUp())
            {
                Hashmap.put("Port Name " + String.valueOf(i), net.getDisplayName());
            }
            i++;
        }
    }

    private void loadInfoGpu(HashMap<String,String> Hashmap) throws SocketException
    {
        if (System.getProperty("os.name").contains(nomOsAcceptes))
        {
            JniEngine Jni = new JniEngine();
            Hashmap.put("VGA", Jni.getInfoGPU());
        }
    }
}

Finally my Data Engine which tries to load all the dlls and change the library path (Most of it is temporary as it is patches on patches)

package Engine;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;

public class DataEngine
{
    static private final String nomLibSigar = "sigar-x86-winnt";
    static private final String nomLibSigar64 = "sigar-amd64-winnt";
    static private final String nomLibJni = "JniEngine";
    static private final String nomLibJni64 = "JniEngine_x64";
    static private final String NomJar86 = "lib_config_x86";
    static private final String nomJar64 = "lib_config_x64";
    static private final String path = "Resources\\";

    static
    {
        try
        {
            if (System.getProperty("os.arch").contains("86"))
            {
                System.loadLibrary(nomLibJni);
                System.loadLibrary(nomLibSigar);
            }
            else
            {
                System.loadLibrary(nomLibJni64);
                System.loadLibrary(nomLibSigar64);
            }
        }
        catch (UnsatisfiedLinkError ex)
        {
            loadJniFromJar();
            loadSigarFromJar();
        }
    }

    public static void loadSigarFromJar()
    {
        try
        {
            File dll;
            InputStream is;
            if (System.getProperty("os.arch").contains("86"))
            {
                is = DataEngine.class.getResourceAsStream(
                        path + nomLibSigar + ".dll");
                dll = File.createTempFile(path + nomLibSigar, ".dll");
            }
            else
            {
                is = DataEngine.class.getResourceAsStream(
                        path + nomLibSigar64 + ".dll");
                dll = File.createTempFile(path + nomLibSigar64, ".dll");
            }
            FileOutputStream fos = new FileOutputStream(dll);
            byte[] array = new byte[1024];
            for (int i = is.read(array);
                    i != -1;
                    i = is.read(array))
            {
                fos.write(array, 0, i);
            }
            fos.close();
            is.close();
            System.load(dll.getAbsolutePath());
            System.setProperty("java.library.path", dll.getAbsolutePath()); 
        }
        catch (Throwable e)
        {
        }
    }

    public static void loadJniFromJar()
    {
        try
        {
            File dll;
            InputStream is;
            if (System.getProperty("os.arch").contains("86"))
            {
                is = DataEngine.class.getResourceAsStream(
                        path + nomLibJni + ".dll");
                dll = File.createTempFile(path + nomLibJni, ".dll");
            }
            else
            {
                is = DataEngine.class.getResourceAsStream(
                        path + nomLibJni64 + ".dll");
                dll = File.createTempFile(path + nomLibJni64, ".dll");
            }
            FileOutputStream fos = new FileOutputStream(dll);
            byte[] array = new byte[1024];
            for (int i = is.read(array);
                    i != -1;
                    i = is.read(array))
            {
                fos.write(array, 0, i);
            }
            fos.close();
            is.close();
            System.load(dll.getAbsolutePath());
        }
        catch (Throwable e)
        {
        }
    }
}

I also have some problem with my main class (NetBeans don't want my JAppletForm to be the main class of my project, but I'll probably recreate the project anyway since the hundreds of patches I tries have corrupted the build. My main class simply load the HashMap with GetMap of ConfigEngine and show it in the console if local or in the JAppletForm if it runs with webstart.

Its a pretty big problem so I'll update my question with all the info you'll need if asked.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
GPierre
  • 100
  • 11
  • possible duplicate of [Load Native Library from Class path](http://stackoverflow.com/questions/23189776/load-native-library-from-class-path) The use of JNLP shouldn't make a difference unpacking and loading the native library. – Alex Barker Sep 23 '14 at 22:15
  • @AlexBarker *"The use of JNLP shouldn't make a difference unpacking and loading the native library."* It does, given the JWS client unpacks the natives and puts them on the run-time class-path of the app. All the Java code needs to do then is load the native (and use it). – Andrew Thompson Sep 24 '14 at 01:49

0 Answers0