Attach library DLL cannot be loaded by application

332 views Asked by At

I am doing bytecode manipulation in java, but it is being done on an external, running JAR file. For this reason, I am using the attach API.

My current problem is that the attach API cannot load a DLL I have in a separate folder. I have proviously had problems with file location but I fixed those and so I know it can see the file, it just can't load it.

My stack trace is as follows:

java.lang.UnsatisfiedLinkError: Can't load library: C:\Users\Jamie\Desktop\Test Rainbow 51\Rainbow Tester\plugins_mod\Natives\64\windows\attach.dll
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.load0(Unknown Source)
    at java.lang.System.load(Unknown Source)
    at RainbowBans.MyPlugin.getAttachProvider(MyPlugin.java:299)
    at RainbowBans.MyPlugin.onStartup(MyPlugin.java:96)
    at joebkt._JoeUtils.LoadPlugins(_JoeUtils.java:2415)
    at joebkt._JoeUtils.Startup(_JoeUtils.java:2502)
    at joebkt.DedicatedServer.startServerConsoleHandler(DedicatedServer.java:44)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:483)
    at java.lang.Thread.run(Unknown Source)

And here is my source code:

    package RainbowBans;

//Just a few imports
import java.awt.Desktop;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//Required when used to start premain by command line.
//import java.lang.ProcessBuilder.Redirect;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.*;

import sun.tools.attach.BsdAttachProvider;
import sun.tools.attach.LinuxAttachProvider;
import sun.tools.attach.SolarisAttachProvider;
import sun.tools.attach.WindowsAttachProvider;
import net.minecraft.server.MinecraftServer;

import com.mojang.authlib.GameProfile;
import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.spi.AttachProvider;

import joebkt.BannedPlayers;
import joebkt.CmdBan;
import joebkt.CmdKick;
import joebkt.PlayerList;
import joebkt._PermMgr;
import PluginReference.*;

public class MyPlugin extends PluginBase{

public static MC_Server server = null;   
String pluginDir = "plugins_mod" + File.separatorChar;
String folderDir = pluginDir + "RainbowBans" + File.separatorChar;
String rainbowDir =   RainbowBans.MyPlugin.class.getProtectionDomain().getCodeSource().getLocation().toExternalForm();
String OS = "Unknown!";

public void onStartup(MC_Server svr){
    System.out.println("Plugin starting! Lets hope this works! :)");
    System.out.println("plugins_mod folder located at:" + new File(pluginDir).getAbsolutePath());
    System.out.println("RainbowBansTransAgent is located at: " + new File(pluginDir + "RainbowBansTransAgent.jar").getAbsolutePath());
    server = svr;   
    System.out.println("Creating files now!");
    File file = new File(folderDir);
    if(file.isDirectory()) System.out.println("Directory already exists!");
    else {
        System.out.println("Creating plugin directory");
        file.mkdir();
    }   
    File errorfile = new File(folderDir + File.separatorChar +     "Rainbowbanserrors.txt");
    if(errorfile.isFile()) System.out.println("File errorfile already exists");
    else
        try {
            System.out.println("Creating stack trace file!");
            errorfile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

    File banfile = new File(folderDir + File.separatorChar + "banmessage.txt");
    if(banfile.isFile()) System.out.println("Banfile already exists!");
    else
        try {
            banfile.createNewFile();
            BufferedWriter writer = new BufferedWriter(new FileWriter(banfile));
            writer.write("You are banned.");
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    File logfile = new File(folderDir + File.separatorChar + "Rainbowbanstransagentlog.txt");
    if(logfile.isFile()) System.out.println("Logfile already exists!");
    else try{
        logfile.createNewFile();
    }catch(IOException e){
    e.printStackTrace();
    }
    JFrame frame = startDialog();
    JMenuBar menu = createMenu();
    frame.setJMenuBar(menu);
    VirtualMachine vm;
    try {

        AttachProvider.setAttachProvider(getAttachProvider());
        vm = VirtualMachine.attach(String.valueOf(Thread.currentThread().getId()));
        String realArch = architecture();
        if(realArch == "64"){
            System.setProperty("java.library.path", new File(folderDir + "Natives" + File.separator + "64" + File.separator + OS + File.separator).getAbsolutePath());
        }else if(realArch == "32"){
            System.setProperty("java.library.path", new File(folderDir + "Natives" + File.separator + "32" + File.separator + OS + File.separator).getAbsolutePath());
        }

            vm.loadAgent(new File(".").getAbsolutePath());
    } catch (AttachNotSupportedException | IOException  | AgentLoadException | AgentInitializationException e) {
        e.printStackTrace();
    }
    //Before using the attach agent, this is how I started the premain in the external JAR (RainbowBansTransAgent.jar)//
    /*File transagent = new File(pluginDir + File.separatorChar + "RainbowBansTransAgent.jar");
    ProcessBuilder pb = new ProcessBuilder("java", "-javaagent:" + transagent.getAbsolutePath(), "RainbowBansTransAgent/TransAgent");
    pb.redirectError(Redirect.appendTo(errorfile));
    pb.redirectOutput(Redirect.appendTo(logfile));
    try{
        pb.start();
    }catch(IOException e){
        e.printStackTrace();
    }
    */
}

private JMenuBar createMenu() {
    JMenuBar menu = new JMenuBar();
    JMenuItem i = new JMenuItem("See message");
    i.addActionListener(getActionListenerForMessage(i));
    menu.add(i);
    JMenuItem w = new JMenuItem("Go to project page");
    w.addActionListener(getActionListenerForWebsites("http://www.project-    rainbow.org/site/index.php?board=9.0"));
    menu.add(w);
    JMenuItem k = new JMenuItem("Go to download page");
    k.addActionListener(getActionListenerForWebsites("http://www.project-    rainbow.org/site/index.php?action=downloads;cat=3"));
    menu.add(k);
    return menu;    
}
//I got the code from http://stackoverflow.com/questions/10967451/open-a-link-in-browser-with-java-button
private void openWebsite(String url){
    Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
    if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
        try {
            desktop.browse(new URL(url).toURI());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
private ActionListener getActionListenerForWebsites(String url) {
    ActionListener al = new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            openWebsite(url);
        }

    };
    return al;
}
private ActionListener getActionListenerForMessage(JMenuItem i) {
    ActionListener al = new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
                try {
                    BufferedReader reader = new BufferedReader(new FileReader(new File(folderDir + File.separatorChar + "banmessage.txt")));
                    String message = reader.readLine();
                    i.setText(message);
                    Timer timer = new Timer();
                    timer.schedule(getTimerTask(i), 5000);
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

    };
    return al;
}
private TimerTask getTimerTask(JMenuItem i) {
    TimerTask task = new TimerTask(){
        @Override
        public void run() {
            i.setText("See message");
        }
    };
    return task;
}
private JFrame startDialog() {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JOptionPane.YES_NO_OPTION);
    frame.setVisible(true);
    frame.setSize(800, 600);
    frame.setAlwaysOnTop(false);
    frame.setBackground(java.awt.Color.yellow);
    return frame;
}
//Copied from CodeCrafter's MultiWorld project.
private AttachProvider getAttachProvider() {
    String os = System.getProperty("os.name").toLowerCase();
    if (os.contains("win") && !os.contains("darwin")) {
        OS = "windows";
        if(architecture() == "64")System.load(new File(pluginDir + "Natives" + File.separator + "64" + File.separator + "windows" + File.separator + "attach.dll").getAbsolutePath());
        else if (architecture() == "32")System.load(new File(pluginDir + "Natives" + File.separator + "32" + File.separator + "windows" + File.separator + "attach.dll").getAbsolutePath());
        else{}
        return new WindowsAttachProvider();
    }
    else if ((os.contains("nix")) || (os.contains("nux")) || (os.indexOf("aix") > 0)) {
        OS = "linux";
        if(architecture() == "64")System.load(new File(pluginDir + "Natives" + File.separator + "64" + File.separator + "linux" + File.separator + "libattach.so").getAbsolutePath());
        else if(architecture() == "32") System.load(new File(pluginDir + "Natives" + File.separator + "64" + File.separator + "linux" + File.separator + "libattach.so").getAbsolutePath());
        else{}
    return new LinuxAttachProvider();
    }
    else if (os.contains("mac")) {
        OS = "mac";
        System.load(new File(pluginDir + "Natives" + File.separator + "64" + File.separator + "mac" + File.separator + "libattach.dylib").getAbsolutePath());
        return new BsdAttachProvider();
    }
    else if (os.contains("sunos")) {
        OS = "solaris";
        if(architecture() == "64")System.load(new File(pluginDir + "Natives" + File.separator + "64" + File.separator + "solaris" + File.separator + "libattach.so").getAbsolutePath());
        else if(architecture() == "32")System.load(new File(pluginDir + "Natives" + File.separator + "64" + File.separator + "solaris" + File.separator + "libattach.so").getAbsolutePath());
    return new SolarisAttachProvider();
    }
    else{
        return null;
    }
}
//Copied from StackOverflow
private String architecture() {
    String arch = System.getenv("PROCESSOR_ARCHITECTURE");
    String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");

    String realArch = arch.endsWith("64")
                  || wow64Arch != null && wow64Arch.endsWith("64")
                      ? "64" : "32";
    return realArch;
}
}
1

There are 1 answers

0
JD9999 On BEST ANSWER

It turns out my problem was that I didn't add my DLL to the java.library.path. Problem solved.