java.lang.UnsatisfiedLinkError: Error looking up function - java

I'm trying to utilize a .dll written in visual basic. I didn't write it so don't have the source code to it. I can load it ok and display the methods inside, but get "java.lang.UnsatisfiedLinkError: Error looking up function" when trying to call one. Here is my code:
package dlltest;
import com.sun.jna.Library;
import com.sun.jna.Native;
import java.lang.reflect.Method;
import java.util.Collection;
public class DllTest {
public interface TC2005 extends Library {
public boolean TCEnabled();
}
public static void main(String[] args) {
TC2005 tc2005 = (TC2005)Native.loadLibrary("TC2000Dev",TC2005.class);
Method[] methods = tc2005.getClass().getDeclaredMethods();
for (Method method:methods) System.out.println(method);
System.out.println("TCEnabled="+tc2005.TCEnabled());
}
}
Here is the output:
public final boolean com.sun.proxy.$Proxy0.TCEnabled()
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'TCEnabled': The specified procedure could not be found.
at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:345)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:325)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at com.sun.proxy.$Proxy0.TCEnabled(Unknown Source)
at dlltest.DllTest.main(DllTest.java:70)
There are many more functions and output but just showing one for clarity.
Been reading posts on the subject all day with no joy. Some talk about compilers mangling the method names and hence need for a FunctionMapper code. To get the real method names everyone says to use Dependency Walker. Tried using that to load the .dll Lots of errors. Also tried loading a .exe that uses the .dll and then running the Profiler option in DW. That locks up the program. (Not Responding).
Suggestions?

Cross check your version. You need function which is not present in loaded .dll . Such cases can be seen with incorrect version.

Related

JDiagram older version throwing StackOverflowError with JRE 8 at ExtendedArrayList.sort

I'm using JDiagram JAR like below
Diagram myDigram = new Diagram();
myDigram.routeAllLinks();
This code works fine when run with JRE 7 however when it is run with JRE 8, following error is being thrown:
java.lang.StackOverflowError
at java.util.Collections.sort(Unknown Source)
at com.mindfusion.common.ExtendedArrayList.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at com.mindfusion.common.ExtendedArrayList.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at com.mindfusion.common.ExtendedArrayList.sort(Unknown Source)
I followed the stack trace to JDiagram decompiled code. Observed that routeAllLinks() calls RouteLinks() on another object (say router) and at one more level deep ExtendedArrayList.sort() which is appeared in error stack trace is called. The "ExtendedArrayList" in JDiagram extends ArrayList and contains a method named "sort()" which has following definition.
public void sort(Comparator<? super T> paramComparator)
{
Collections.sort(this, paramComparator);
}
On Google I found out that JRE 8 has introduced List.sort() and delegates the Collections.sort() calls to collection's (ExtendedArrayList in my case) sort method. And so library ExtendedArrayList.sort() became an override. And it creates an infinite recursion which results in stackoverflow. I could reproduce this issue even with small piece of code as well now.
Also
Our original class which creates JDiagram object, is being loaded at runtime by some other component in our product. We have very little control over the loading of our program.
We have found out that latest version of JDiagram has fixed this issue by replacing sort() with sortJ7() method. However, we cannot upgrade the library at this moment. JDiagram is a licensed API.
ExtendedArrayList is being instantiated by JDiagram internally and so we cannot alter it from our code.
We have tried following solutions which didn't work so far
Java Proxy: Because our code does not call ExtendedArrayList directly
and also 'Diagram' does not have any interface.
Spring AOP: We are
not using spring and also our program is loaded runtime by other
component.
AspectJ: By now, this was apparently a solution. However,
it also didn't work as we are not able to weave our program at
runtime. Not sure if someone could make it work.
Kindly let me know if any point needs elaboration.
Any help is welcome. Thanks.
UPDATE
So far, javassist is the best approach however there JDiagram obfuscation is preventing the solution to work correctly. We have kind of assumed that it is impossible (have to say) to fix considering our release date on our head. We have started process to upgrade library. And meanwhile removed a small feature from our application which was being provided by routeAllLinks() method.. :-(
thanks everyone for your help. I'll be continuing my research on this issue as I found it really intriguing and challenging.. I'll update the post if I could resolve it.. And I'll be giving bounty to #gontard for his javassist approach as I'm continuing my research with it. Thanks.
I have reproduced your problem with a basic example:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class ExtendedArrayList<E> extends ArrayList<E> {
#Override
public void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}
}
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws Exception {
ExtendedArrayList<String> arrayList = new ExtendedArrayList<String>();
arrayList.addAll(Arrays.asList("z", "y", "x"));
arrayList.sort(String::compareTo); // -> java.lang.StackOverflowError
}
}
I was able to bypass the java.lang.StackOverflowError by renaming the method using javassist:
import java.util.Arrays;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class Main {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("ExtendedArrayList");
CtClass[] sortParams = new CtClass[]{ pool.get("java.util.Comparator")};
CtMethod sortMethod = ctClass.getDeclaredMethod("sort", sortParams);
sortMethod.setName("sortV7"); // rename
ctClass.toClass();
ExtendedArrayList<String> arrayList = new ExtendedArrayList<String>();
arrayList.addAll(Arrays.asList("z", "y", "x"));
System.err.println(arrayList); // print [z, y, x]
arrayList.sort(String::compareTo);
System.err.println(arrayList); // print [x, y, z]
}
}
I have not tried with your version of JDiagram because I get only the last (Java 8 compatible) version on their website.
Think about decompiling the library and fixing the issue by yourself. You could use this fixed package as a workaround.
An alternative would be, to place a fixed version of the class in your code. Same package like in the library and same class name of course:
com.mindfusion.common.ExtendedArrayList
Maybe you have to configure the classloader to load your class instead of looking up the faulty class in the library first. Options like "parent first" or simply accessing the class from your code once before calling the library could make the deal.
I see that the loading of your program is not controlled by you.
Perform the following steps:
Include the jar(javassist) of the program that could change the "sort" method name to any other name that could avoid overriding the sorting method
Load the jar's (javassist) main class by reflection class.forName(""); in the beginning of your program's main method
Call the jar's (javassist) method to perform the required changes you need on the methods
This way you could be sure that any jar (javassist)is loaded and is ready to be used.

ClassNotFoundException when loading a class at runtime

Using the Bukkit-API I'm currently trying to create a plugin which can compile java code of a given pastebin link at runtime and execute that code. Everything is working so far except for one thing: I'm getting a ClassNotFoundException when I'm trying to access one of the already loaded plugins. (I'm not getting an exception when I'm using Bukkit-API methods!)
All plugin jars have been added to the classpath; it currently looks like this:
/home/cubepanel/test-network/jars/craftcubbit.jar:/home/cubepanel/test-network/servers/ProHub/plugins/MultiCubeHub.jar:/home/cubepanel/test-network/servers/ProHub/plugins/MultiCubeCore.jar:
The classes I tried to load dynamically:
ClassNotFoundException for MutliCube
import be.multicu.core.MultiCube;
public class Test{
public void debug() {
System.out.println(MultiCube.getInstance());
}
}
Working
import org.bukkit.Bukkit;
public class Test{
public void debug() {
System.out.println(Bukkit.getClass().getName());
}
}
Sourcecode of RuntimeCompiler.java: http://paste.multicu.be/axigofekip.avrasm (It's a bit long, thats why I used a pastebin link)
I also noticed that I'm getting an compilation error when I removed the classpath of MultiCube.jar which means that the classpath must be correct since the sourcecode can be compiled.
EDIT: I was able to fix it by adding MultiCube.class.getClassLoader() as an argument in the constructor of my URLClassLoader

Why isn't my ResourceBundleControlProvider being loaded?

I thought I would use the new ResourceBundleControlProvider framework in Java 8 to fix something which Oracle themselves will never fix - the default encoding used when reading resource bundles.
So I made a control:
package com.acme.resources;
import java.io.IOException;
import java.util.Locale;
import java.util.ResourceBundle;
public class AcmeResourceBundleControl extends ResourceBundle.Control
{
#Override
public ResourceBundle newBundle(String baseName, Locale locale, String format,
ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
throw new UnsupportedOperationException("TODO");
}
}
Then I made a provider:
package com.acme.resources;
import java.util.ResourceBundle;
import java.util.spi.ResourceBundleControlProvider;
public class AcmeResourceBundleControlProvider implements ResourceBundleControlProvider
{
private static final ResourceBundle.Control CONTROL = new AcmeResourceBundleControl();
#Override
public ResourceBundle.Control getControl(String baseName)
{
if (baseName.startsWith("com.acme."))
{
return CONTROL;
}
else
{
return null;
}
}
}
Then in META-INF/services/java.util.spi.ResourceBundleControlProvider:
com.acme.resources.AcmeResourceBundleControlProvider
Then I just tried to run our application from IDEA and I find that it never loads my provider (otherwise the exception would be raised.)
I have checked the names and they all seem to match up. I have checked the compiler output directory IDEA is using and it does contain the service file. I wrote a simple test program which just tries to look up the service:
public static void main(String[] args)
{
for (ResourceBundleControlProvider provider :
ServiceLoader.load(ResourceBundleControlProvider.class))
{
System.out.println(provider.getClass());
}
}
This does print out one entry which is the name of my implementation class. So the issue is not in the service file.
If I breakpoint inside ResourceBundle, I seem to be able to access the custom provider class. Initial forays into the debugger show that ServiceLoader isn't finding any implementations, but I can't figure out why. I'm sure there is some dodgy class loader magic going on which results in not loading my class. :(
Some scary documentation on the Javadoc makes it sound like it might have to be installed as a global extension. If that really is the case, it's a bit of a shame, because it seemed like a useful way to override the default (and in my opinion broken) behaviour. But I also read the tutorial on the matter and it didn't seem to be describing anything like that (unless the good behaviour was pulled out of Java 8 at the very last minute and the docs are out of date!)
The tutorial does state that the JAR containing the ResourceBundleControlProvider must be in the JVM's system extension directory. Section 6 of the tutorial describes the requirement:
java -Djava.ext.dirs=lib -cp build RBCPTest
When you install a Java extension, you typically put the JAR file of the extension in the lib/ext directory of your JRE. However, this command specifies the directory that contains Java extensions with the system property java.ext.dirs.
The JavaDoc for ServiceLoader.loadInstalled() also states that providers on the application's class path are ignored.
Your problem is that the java.util.ResourceBundle that comes with the JVM does a ServiceLoader.loadInstalled(ResourceBundleControlProvider.class) to obtain a list of providers in the static initializer, and uses the thus obtained list ever after.

Jar files in JSP not loading properly

This might be a duplicate, but I cannot find an answer using the below answers and many other sites on the internet...
My conundrum:
I am attempting to (poorly) run some classes from a jar in jsp. Effectively what I have is the following:
<%#page import="edu.cs242.hadoop.*" %>
<%
... do some stuff ...
MRSearcher ss = new MRSearcher();
... do some stuff ...
%>
But every time I try to run the jsp I get the following error:
An error occurred at line: 32 in the jsp file: /hadoop.jsp
MRSearcher cannot be resolved to a type
My webapp structure looks like:
/
|hadoop.jsp
|lucene.jsp
|index.jsp
|WEB-INF/
|lib/
|lucene.jar
|hadoop.jar
|classes/
|*.java for our hadoop.jar
I've tried calling the jar itself and compiling the java through tomcat, both produce the same results.
Here is a snippet from our MRSearcher class:
package edu.cs242.hadoop;
import java.io.*;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
/**
* Created by cloudera on 3/10/14.
*/
public class MRSearcher {
MRSearcher() {}
public String[] run(String arg1, String arg2) {
String[] things = new String[] {};
// do stuff
return things;
}
}
There are other classes, but this one is the one that allows us to interface with the rest of the program. The main is in a file called: Main.java, and it does nothing but runs this for command line output. The syntax is correct as we can run the main and retrieve output.
I don't mean to sound insolent, but please don't comment on the futility and awfulness of including things like JAR files in JSP. This is never going to production, it's a school project that doesn't need the necessity of correctness, it needs the necessity of functioning. If I were doing this for a job I would do it right, but right now I don't care about learning about the correct way to separate logic and presentation layers in JSP -- I can do that just fine in other languages and understand the concept very well.
I have looked through and attempted to use the following solutions before posting this, all of this has failed:
how to run jar file methods in jsp
How to call method from jar file in JSP?
how to reference an external jar in jsp app?
And more to try to solve this problem.
In WEB-INF/classes/ you must have MRSearcher.class file. Keep in mind JSP files are compiled first time you access it, so your project can compile although your JSP are not well.
On the other hand, your MRSearcher() constructor must be public, if you omitte this, by default the constructor will be package and cannot be accessed from other packages. Check if your Main.java class is in same package of MRSearcher. If yes, this is why it can invoke MRSearcher constructor.
I hope this helps you.
Regards,

Receiving multiple syntax errors when using registerServlet method

I am trying to implement JUnit unit testing using a ServletUnit to test a servlet, specifically a java file named SignedNotesServlet.java . This test class is in the same directory as SignedNotesServlet.java . I am using Eclipse.
However, I am having trouble writing the correct syntax for registerServlet method that is part of ServletUnit and HttpUnit. I have not yet run the program. The errors I am receiving are
Syntax error on tokens, FormalParameter expected instead
Syntax error on token "class", identifier expected
Syntax error on token(s), misplaced construct(s)
Syntax error on token ""SignedNotesServlet"", invalid FormalParameterList
Here is my code:
package notetaker;
import com.meterware.servletunit.ServletRunner;
import com.meterware.servletunit.ServletUnitClient;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.fail;
public class SignedNotesServletTest {
ServletRunner sr = new ServletRunner();
sr.registerServlet( "SignedNotesServlet", SignedNotesServlet.class.getName() );
private SignedNotesServlet signednotes;
#Test
public void test() {
fail("Not yet implemented");
}
}
I think I correctly added the jar file the buildpath, using instructions from http://tinyurl.com/ku7huss . I used http://tinyurl.com/b55fn as my main reference but am also looking at the few registerServlet examples on the web (I can't post those links for reference since I need a 10 reputation to post more than 2 links). I am not entirely sure what could be wrong since I basically copy-pasted from the second website and made (what I thought) were appropriate changes.
I also thought that maybe something was wrong with "SignedNotesServlet" since there were quadruple quotes in the error, and I removed them, but it still doesn't work out, and I don't think that would have been correct syntax anyway, based on the examples.
This is the problem:
sr.registerServlet( "SignedNotesServlet", SignedNotesServlet.class.getName() );
This statement isn't in a method or constructor - it needs to be. Either put it within the test itself or put it in a setup method. If you put that code into the individual test, I'd also recommend making sr a local variable for that test. If you put it into a setup method, you'd need sr to be an instance variable still, but I'd suggest making it private and giving it a more useful name.
I am not entirely sure what could be wrong since I basically copy-pasted from the second website
But you copied it into an inappropriate place. Note that this has nothing to do with servlets, JUnit, ServletUnit or your build path - it's simply invalid Java.

Categories

Resources