JNA free memory created in the shared object dll - java

I tried libvirt java bindings and always get Access Violation error when the library try to use Native.free method to free memory allocated in the dll, so I write the following simple test.
public class HelloWorld {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("msvcrt", CLibrary.class);
Pointer _strdup(String src);
}
public static void main(String[] args) {
Pointer p = CLibrary.INSTANCE._strdup("HelloWorld");
Native.free(Pointer.nativeValue(p));
}
}
My environment is as following:
Windows 7 Ultimate SP1 64Bit, Jdk&Jvm is also 64bit(1.8.0_101), Eclipse Neon Release 64Bit, JNA version 4.2.2.
The program stop at Native.free line, and prompt App crash dialog, information is as following:
Problem signature:
Problem Event Name: APPCRASH
Application name: javaw.exe
Application version: 8.0.1010.13
Application timestamp: 576a4c7e
Fault module name: StackHash_c84f
Faulty module version: 6.1.7601.18247
Faulty module timestamp: 521eaf24
Exception code: c0000374
Exception offset: 00000000000c4102
OS version: 6.1.7601.2.1.0.256.1
Locale ID: 2052
Additional Information 1: c84f
Additional information 2: c84f3cec06e628f5bb4621d27c86f80d
Additional Information 3: 3b2e
Additional Information 4: 3b2e22e89759af30ea1b1d716fbf08f3
So I wondering if this way to free memory created in dll is wrong? Can you give me some advice, thanks!

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public class MemoryTest {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
Pointer strdup(String src);
}
public static void main(String[] args) {
Pointer p = CLibrary.INSTANCE.strdup("HelloWorld");
Native.free(Pointer.nativeValue(p));
System.gc();
}
}
this test did run on Linux Ubuntu64 16.04 without any crash.

Related

Access com.sun.* classes from openjdk11

I have a Spring Boot application and I want to use the class com.sun.management.ThreadMXBean, and the method getThreadAllocatedBytes to collect information about allocated bytes in my application. I dockerized it and used OpenJDK 11 in the dockerfile, because Oracle JDK cannot be dockerized. I'm using docker image jboss/base-jdk:11 and deploy the application in a Wildfly 16.
Unfortunately OpenJDK does not support the com.sun.* packages. Is there any way I can work around this problem and use com.sun.management.ThreadMXBean.getThreadAllocatedBytes in an OpenJDK?
So, this worked for me with AdoptJdk 11 (which is a build of OpenJdk):
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.lang.management.ThreadMXBean;
public class Test {
public static void main(String[] args) {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
try {
Method getBytes = threadMXBean.getClass().getMethod("getThreadAllocatedBytes", long.class);
getBytes.setAccessible(true);
long threadId = Thread.currentThread().getId();
long bytes = (long)getBytes.invoke(threadMXBean, threadId);
System.out.println(bytes);
} catch (Throwable e) {
System.out.println(e);
}
}
}
Invoke with
C:\workspaces\devtools\jdks\adoptjdk\jdk-11.0.2+9\bin\javac Test.java
C:\workspaces\devtools\jdks\adoptjdk\jdk-11.0.2+9\bin\java --add-exports jdk.management/com.sun.management.internal=ALL-UNNAMED Test
Also, in that docker image it works
FROM jboss/base-jdk:11
COPY . /app/
WORKDIR /app
CMD java --add-exports jdk.management/com.sun.management.internal=ALL-UNNAMED Test
And run it in docker:
docker build -t openjdktest .
docker run -it openjdktest
EDIT
Oh, there seems to be an even simpler alternative. Just cast your ThreadMXBean object directly to com.sun.management.ThreadMXBean:
import java.lang.management.ManagementFactory;
import com.sun.management.ThreadMXBean;
public class Test {
public static void main(String[] args) {
ThreadMXBean threadMXBean = (ThreadMXBean)ManagementFactory.getThreadMXBean();
long bytes = threadMXBean.getThreadAllocatedBytes(Thread.currentThread().getId());
System.out.println(bytes);
}
}
This can be run, even without the --add-exports JVM argument.
So, I just downloaded OpenJDK 11 and extracted its sources.
Inside I found ThreadImpl, which implements java.lang.management.ThreadMXBean
And infact you can find it under
ThreadMXBean has indeed a getThreadAllocatedBytes method
protected long[] getThreadAllocatedBytes(long[] ids) {
boolean verified = verifyThreadAllocatedMemory(ids);
long[] sizes = new long[ids.length];
java.util.Arrays.fill(sizes, -1);
if (verified) {
getThreadAllocatedMemory1(ids, sizes);
}
return sizes;
}

Netbeans fails to find main class when creating anonymous subclass of inner class of anonymous subclass

When I attempt to create a new anonymous Action subclass inside the initialization of an anonymous subclass of its containing class's containing class, Netbeans suddenly fails to find the main class when running, despite being able to clean+build with no problem and to run with this code commented out.
Code structure:
Main package:
Main class <-- currently looking at this file
public void run(...) (called in main(String[] args))
Actor a = new Actor() {
Script script = new Script();
{ (Actor instance initiation code)
script.new Action(0) {...} causes breakage
Package actor
public abstract class Actor
public class Script
public abstract class Action
Replicated in a simple class:
package tests;
public class ClassTester {
public static void main(String[] args) {
ClassTester tester = new ClassTester();
tester.run();
}
public void run() {
final Inner1 A = new Inner1() {
{
B = this.new Inner2() {
#Override
public void run() {
System.out.println("Hello, world!");
}
};
}
};
A.B.run();
}
public class Inner1 {
public Inner2 B;
public abstract class Inner2 implements Runnable {
}
}
}
-->
Error: Could not find or load main class tests.ClassTester
Java Result: 1
Interestingly, -XX:+PrintCompilation reveals that something runs before the crash:
50 1 java.lang.String::hashCode (55 bytes)
50 2 java.lang.String::charAt (29 bytes)
Error: Could not find or load main class tests.ClassTester
Java Result: 1
Product Version: NetBeans IDE 7.3.1 (Build 201306052037)
Java: 1.7.0_25; Java HotSpot(TM) 64-Bit Server VM 23.25-b01
Runtime: Java(TM) SE Runtime Environment 1.7.0_25-b17
System: Windows 7 version 6.1 running on amd64; Cp1252; en_US (nb)
Cleaning and building and restarting Netbeans have not resolved the problem. Is this fixable or a bug in Netbeans?
I was able to reproduce the issue in NetBeans 7.3.1. The problem appears to be related to bug #224770. The fix summary is #224770: making handling of new with enclosing expression more similar to vanilla javac, while preserving the correct outputs from the API.
You have two options.
Upgrade NetBeans to 7.4 or newer. I tested the code in 7.4 and it worked properly.
Keep using NetBeans 7.3, and don't use "this.new". Change line 11 to this:
B = new Inner2() {

JNA library and native library not found error

I want to use JNA to detect foreground application on Linux (Ubuntu 14). I followed this link
Find out what application (window) is in focus in Java
but I got the following error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'XLib': Native library (linux-x86-64/libXLib.so) not found in resource path ([file:/home/zzhou/workspace/home_prioritization_plus/bin/, file:/home/zzhou/Downloads/jna-4.1.0.jar, file:/home/zzhou/Downloads/jna-platform-4.1.0.jar])
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:271)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398)
at com.sun.jna.Library$Handler.<init>(Library.java:147)
at com.sun.jna.Native.loadLibrary(Native.java:412)
at com.sun.jna.Native.loadLibrary(Native.java:391)
at FunctionalityTest$XLib.<clinit>(FunctionalityTest.java:15)
at FunctionalityTest.main(FunctionalityTest.java:23)
The code is:
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.unix.X11;
import com.sun.jna.win32.StdCallLibrary;
public class FunctionalityTest {
static class Psapi {
static { Native.register("psapi"); }
public static native int GetModuleBaseNameW(Pointer hProcess, Pointer hmodule, char[] lpBaseName, int size);
}
public interface XLib extends StdCallLibrary {
XLib INSTANCE = (XLib) Native.loadLibrary("XLib", Psapi.class); // <-- PROBLEM
int XGetInputFocus(X11.Display display, X11.Window focus_return, Pointer revert_to_return);
}
public static void main(String args[]) {
if(Platform.isLinux()) { // Possibly most of the Unix systems will work here too, e.g. FreeBSD
final X11 x11 = X11.INSTANCE;
final XLib xlib= XLib.INSTANCE;
X11.Display display = x11.XOpenDisplay(null);
X11.Window window=new X11.Window();
xlib.XGetInputFocus(display, window,Pointer.NULL);
X11.XTextProperty name=new X11.XTextProperty();
x11.XGetWMName(display, window, name);
System.out.println(name.toString());
}
}
}
To import JNA library, I downloaded jna and jna-platform from https://github.com/twall/jna and use Configure Build Path... in Eclipse to add library. I did not install anything. May that be the source of the problem?
Thanks for your help.
Afaik, even for JNA, you have to load the library in Java in order for JNA to find it. (tested for win32, not linux)
Try this just above Native.loadLibrary:
System.loadLibrary("XLib");

Using DLL in java through JNA

I am using dll in java using JNA, but i am getting below error
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'GetStatus': The specified procedure could not be found.
Not getting how to resolve this issue?
Please help.
Here is java code
import com.sun.jna.Library;
import com.sun.jna.Native;
/** Simple example of native library declaration and usage. */
public class First {
public interface TEST extends Library {
public String GetStatus();
}
public static void main(String[] args) {
TEST obj = (TEST ) Native.loadLibrary("TEST ", TEST .class);
System.out.println( obj.GetStatus());
}
}
This Nugget is super easy to use and works perfectly. https://www.nuget.org/packages/UnmanagedExports
You need Visual Studio 2012 (express).
Once installed, just add [RGiesecke.DllExport.DllExport] before any static function you want to export. That's it!
Example:
C#
[RGiesecke.DllExport.DllExport]
public static int YourFunction(string data)
{
/*Your code here*/
return 1;
}
Java
Add the import at the top:
import com.sun.jna.Native;
Add the interface in your class. Its your C# function name preceded by the letter "I":
public interface IYourFunction extends com.sun.jna.Library
{
public int YourFunction(String tStr);
};
Call your DLL where you need it in your class:
IYourFunction iYourFunction = (IYourFunction )Native.loadLibrary("full or relative path to DLL withouth the .dll extention", IYourFunction.class);//call JNA
System.out.println("Returned: " + IYourFunction.YourFunction("some parameter"));
EDIT:
If the DLL is 32bit, the JDK/JRE has to be 32bit as well. Add the following check to your code:
if(!System.getProperty("os.arch").equals("x86")) {
throw new Exception(".NET DLL " + "32bits JRE/JDK is required. Currently using " + System.getProperty("os.arch") + ".\r\nTry changing your PATH environement variable.");
}

JNA access to 64-bit DLL (Windows7 64-bit)

Could you please advice. I have simple DLL (under Windows 7 64-bit) and simple Java code with JNA access to this DLL.
The problem is when I use 64-bit version of this DLL looks like I can't get parameter from Java in my DLL test function giveIntGetInt, and I have no problem when I use 32-bit DLL.
Where I was wrong?
Thank you!
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
/** Simple example of native library declaration and usage. */
public class HelloWorld {
public interface simpleDLL extends Library {
simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(
(Platform.isWindows() ? "simpleDLL" : "simpleDLLLinuxPort"), simpleDLL.class);
int giveIntGetInt(int a); // int giveIntGetInt(int a);
}
public static void main(String[] args) {
int b = simpleDLL.INSTANCE.giveIntGetInt(2);
System.out.println("Hello, World\n");
System.out.println(String.format("Argument %d", b));
}
}
this is C dll method:
int simpleDLL::giveIntGetInt(int a)
{
return 2*a;
}
For example, this is I've got with 64-bit dll:
Hello, World
Argument 181140
32-bit dll:
Hello, World
Argument 4

Categories