I have two DLL's: a directx dll, which exports GetNativeBuffer, and an opengl dll, which does the same.
I use the following Java class to call GetNativeBuffer, to read an image from the loaded dll.
class DllLoader {
private ByteBuffer Buffer = null;
private BufferedImage Image = null;
public boolean LibraryLoaded = false;
private static native void GetNativeBuffer(IntBuffer Buffer);
private int ByteSize = 0, Width = 0, Height = 0;
public DllLoader(ByteBuffer Buffer, int ImageWidth, int ImageHeight) {
this.Buffer = Buffer;
}
}
Problem: If both DLL's are loaded by the program, how do I specify which one to read from?
Do I have to make two separate classes? Do I have to rename the functions and have two native functions?
You should make two classes, one for each DLL. If you are naming your java classes identically, it might be easier to separate them into different subpackages, for example:
package com.stackoverflow.jni.opengl;
/*
* GENERATE HEADER FILE FROM GENERATED CLASS AS NEEDED VIA
* javah com.stackoverflow.jni.opengl.NativeClazz
*/
public class NativeClazz {
/**
* Load C++ Library
*/
static {
// Always fun to do this in a static block!
System.loadLibrary("OpenGL");
}
private static native void GetNativeBuffer(IntBuffer Buffer);
}
and
package com.stackoverflow.jni.directx;
/*
* GENERATE HEADER FILE FROM GENERATED CLASS AS NEEDED VIA
* javah com.stackoverflow.jni.directx.NativeClazz
*/
public class NativeClazz {
/**
* Load C++ Library
*/
static {
// Always fun to do this in a static block!
System.loadLibrary("DirectX");
}
private static native void GetNativeBuffer(IntBuffer Buffer);
}
My personal preference is to keep any class containing JNI methods "utility-only" (private constructor), leaving them lean and mean (no internal variables unless necessary) and transfer data back and forth within beans via function call parameters.
Related
Whatever the reason, I have the following hashCode implemented in my abstract class.
#MappedSuperclass
abstract Some {
#Override
public boolean equals(final Object obj) {
// ...
}
#Override
public int hashCode() {
return getClass().hashCode(); // TODO: cache, maybe?
}
}
Can I cache the value of the getClass().hashCode()?
Is there any possibility of the value being changed while running in a JVM?
Is this some kind of the premature optimization shit?
Can I cache the value of the getClass().hashCode()?
You can, but ...
Is there any possibility of the value being changed while running in a JVM?
No possibility. The class of a Java object cannot change, and the hashcode of a Java Class object (which is the result type for getClass()) cannot change.
Is this premature optimization?
Probably yes1.
However, using the hashcode of the object's class as the hashcode of an object is a very bad idea from a performance perspective.
Doing that means that all instances of the class (e.g. Some) will have the same hashcode2. That will lead to a bazillion hash collisions, and make most HashSet and HashMap operations O(N) or O(logN) (depending on your Java version) rather than O(1).
1 - I am assuming you have not done a bunch of performance analysis that you haven't told us about. If you had already done the analysis, then maybe this is not a premature optimization.
2 - I am assuming that the Some::hashCode method is not overridden to something more sensible by concrete subclasses of Some.
Stephen C's answer is a good answer. However, for the sake of completeness, I feel the need to add to that, that if a class is loaded by, let's say, two different class loaders, then for that class getClass().hashcode() will return two different values.
For verifying that, I wrote a program and loaded a class with System class loader, and then with my own custom class loader. Both return different hashcode():
First the code for Custom class loader I copied from https://www.digitalocean.com/community/tutorials/java-classloader:
package com.journaldev.classloader;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* Our Custom ClassLoader to load the classes. Any class in the
* com.journaldev package will be loaded using this ClassLoader.
* For other classes, it will delegate the request to its Parent
* ClassLoader.
*/
public class CCLoader extends ClassLoader {
/**
* This constructor is used to set the parent ClassLoader
*/
public CCLoader(ClassLoader parent) {
super(parent);
}
/**
* Loads the class from the file system. The class file should be located in
* the file system. The name should be relative to get the file location
*
* #param name Fully Classified name of the class, for example, com.journaldev.Foo
*/
private Class getClass(String name) throws ClassNotFoundException {
String file = name.replace('.', File.separatorChar) + ".class";
byte[] b = null;
try {
// This loads the byte code data from the file
b = loadClassFileData(file);
// defineClass is inherited from the ClassLoader class
// that converts byte array into a Class. defineClass is Final
// so we cannot override it
Class c = defineClass(name, b, 0, b.length);
resolveClass(c);
return c;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* Every request for a class passes through this method. If the class is in
* com.journaldev package, we will use this classloader or else delegate the
* request to parent classloader.
*
* #param name Full class name
*/
#Override
public Class loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("com.journaldev.")) {
return getClass(name);
}
return super.loadClass(name);
}
/**
* Reads the file (.class) into a byte array. The file should be
* accessible as a resource and make sure that it's not in Classpath to avoid
* any confusion.
*
* #param name Filename
* #return Byte array read from the file
* #throws IOException if an exception comes in reading the file
*/
private byte[] loadClassFileData(String name) throws IOException {
InputStream stream = getClass().getClassLoader().getResourceAsStream(
name);
int size = stream.available();
byte buff[] = new byte[size];
DataInputStream in = new DataInputStream(stream);
in.readFully(buff);
in.close();
return buff;
}
}
Then the Test class and main method which we will use for loading the Test class with different class loaders:
package com.journaldev.test;
import com.journaldev.classloader.CCLoader;
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(new CCLoader(ClassLoader.getSystemClassLoader())
.loadClass(Test.class.getCanonicalName()).hashCode());
System.out.println(ClassLoader.getSystemClassLoader()
.loadClass(Test.class.getCanonicalName()).hashCode());
}
}
Output shows different hashcodes for the same class loaded with different Class Loaders:
1554547125
1072591677
I'm controlling some external device using my android app, and in order to control this device it provides an sdk which is a C#(.dll) files, I know how to load .dll libraries into java and how to use it, but I can't access a lot of methods inside these libraries because it takes C# native arguments like structs which is not available in Java, and I tried equivalents in Java like classes with public elements to represent a struct but it keeps give me the error: java.lang.IllegalArgumentException: Unsupported argument type
This is how I deal with the Library(using jna):
import outsource.classes.MyClass;
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Test {
public interface simpleDLL extends Library {
long H264_DVR_GetLastError(int num); // accessed without any problems
boolean H264_DVR_SetDVRMessCallBack(MyClass obj, long num); // this "MyClass" is mainly a STRUCT in the C# sdk
}
static
{
System.loadLibrary("NetSdk");
}
public static void main(String args[]) {
simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(("NetSdk"),
simpleDLL.class);
System.out.println(INSTANCE.H264_DVR_GetLastError(4));
System.out.println(INSTANCE.H264_DVR_SetDVRMessCallBack(new MyClass(),
0));
}
}
And this is how I created MyClass.Class:
public class MyClass() {
public String Id = "myDevice";
public String UserName = "admin";
public int password = 1234;
}// also tried declaring the values inside a constructor but nothing changed
and this is how the struct defined inside the sdk:
typedef struct _DEVICEINFO
{
char id[64];
char user[64];
int pw;
}DEVICEINFO,*LP_DEVICEINFO;
p.s. I know there are some ways to write an android app with C# code using VisualBasic(e.g vs-android) but that won't work in my case as the app is already written and running with java and it's pretty huge with a lot of other functionalists so it can't be rewritten.
I am developing an Eclipse RCP application and I recently started to use Groovy in it. So 99% of my code is still Java.
I read that it is possible to use Groovy to override and add methods to Java classes and I was able to test this by adding a method to the java.lang.String.
But this only works when I use the string in a Groovy class. The overridden method is not considered as being overridden in a Java class.
Here's some code:
/*
* This is a Java class
*/
public class CTabItem {
...
private API
...
public void setControl(Control control){
private API
}
}
/*
* This is also a Java class
*/
public class Control {
...
private API
...
}
/*
* This is also a Java class
*/
public class OtherClass {
...
private API
...
private void someMethodIDontKnow(){
Control control = new Control();
CTabItem tab = new CTabItem();
tab.setControl(control);
}
}
/*
* This is a Groovy class
*/
public class MyViewPart extends org.eclipse.ui.part.ViewPart {
....
public void createPartControl(Composite parent) {
/* parent (or the parent of parent) is a Control
which is set somewhere in a CTabItem to which
I don't get access */
}
}
I need to get the tab from the control. But since it's not me who instantiates MyViewPart, but some private API, I have no access to it.
Is there something Groovy could do for me here? Any suggestion or code is welcome. Thank you!
The short answer is: no, it's not possible if the code creating the object and calling the method is pure Java (i.e., non-Groovy) code. Groovy does its magic by intercepting all method calls on objects (both Java objects and Groovy objects) and using its ExpandoMetaClass to add the behavior. However, it can't change how pure Java code determines which method to call on a pure Java class. To see, run the following sample code:
// UseTheString.java (a pure Java class)
public class UseTheString {
public static void main(String[] arg) {
String s = "Hello world";
System.out.println(s);
System.out.println(s.substring(1));
ModifyStringClass.messWithMetaClasses(s);
System.out.println(s.substring(1));
}
}
and
// ModifyStringClass.groovy (a Groovy class)
class ModifyStringClass {
public static messWithMetaClasses(String t) {
java.lang.String.metaClass.substring = { int n -> "!" }
println(t.substring(1))
}
}
You'll get the output:
Hello world
ello world
!
ello world
As you can see, Groovy can override the method on a pure Java object if it is called from other Groovy code, but it can't change how the Java code uses it.
I am wondering is it possible to verify in Java under the Android SDK that a method in a Java class implemented as a native JNI method was resolved statically? Below there is an explanation of what I am looking for.
I have a Java class that is partially implemented as a JNI class. This class can be initialized statically if the corresponding JNI library has been created as a static library (libhelper.a, for instance). Or it can be initialized dynamically if the corresponding JNI library is implemented as a dynamic library (libhelper.so, for instance). In case of dynamic initialization the class should have a static initializer that loads the dynamic library – libhelper.so. I am using both case and I want to keep the same source code for both of them. For this purpose I would like to verify in the static initializer if the corresponding native methods has been already resolved. If it is true, I do not need to load dynamic library. If it is false, it means that I have to load dynamic library. The problem is I do not know how to verify that a method in the class has been already resolved.
The sample below has incorrect lines, that show my intention.
package com.sample.package;
public class MyUtilityClass
{
private static final String TAG = "MyUtilityClass";
public MyUtilityClass () {
Log.v(TAG, " MyUtilityClass constructor");
}
public static native int initMyHelperClass();
public static native int performHelpAction(String action);
public static native int uninitMyHelperClass();
static {
try {
/* Here I want to verify that the native method
initMyHelperClass has has been already resolved.
In this code snippet I am just comparing it to null,
which is not correct. It should be something different. */
if (initMyHelperClass == null) {
/* initMyHelperClass has not been resolved yet,
load the dynamic library - libhelper.so */
System.loadLibrary("helper");
}
} catch (UnsatisfiedLinkError ule) {
/*Library not found. We should throw second exception. */
throw ule;
}
}
}
Thank you.
You could use UnsatisfiedLinkError and a dummy method to check if a given class' native methods are loaded:
private static native void checkMe(); // does nothing
static {
try {
checkMe();
} catch (UnsatisfiedLinkError e) {
System.loadLibrary("checkLibrary");
}
}
I have a C header to a certain library I need to access. So I used JNAerator to do the boring transitions of code - after I read that people recommend it these days. Seems to be quite solid from what I see:
public class Z3_apiLibrary implements Library {
public static final String JNA_LIBRARY_NAME = LibraryExtractor.getLibraryPath("z3_api", true, z3_api.Z3_apiLibrary.class);
public static final NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(JNA_LIBRARY_NAME, com.ochafik.lang.jnaerator.runtime.MangledFunctionMapper.DEFAULT_OPTIONS);
static {
Native.register(JNA_LIBRARY_NAME);
}
public static interface Z3_lbool {
public static final int Z3_L_FALSE = -1;
public static final int Z3_L_UNDEF = 0;
public static final int Z3_L_TRUE = 1;
};
public static interface Z3_symbol_kind {
public static final int Z3_INT_SYMBOL = 0;
public static final int Z3_STRING_SYMBOL = 1;
};
The complete code is at my GitHub.
Now I want to instantiate the dll as an object, and pass the header information from my written interface as a wrapper:
public class z3_Solver {
public static void main(String[] args) {
Z3_apiLibrary solver = (Z3_apiLibrary) Native.loadLibrary("z3", Z3_apiLibrary.class);
Z3_apiLibrary config = new Z3_apiLibrary.Z3_config(); // will not work!
}
To my surprise this isn't working. .Z3_config() is abstract. mk_config is static and native. So I cannot resolve that either.... Actually I thought to need to pass the Path to the Native.loadLibrary function as a parameter to locate the dll. I put the dll in the same path as the Java class. Which is confusing and I suspect also wrong.
So what's the right way to instantiate that JNAerator generated interface?
The header you posted does not define what Z3_config is, it only says DEFINE_TYPE(Z3_config); This header does not have enough information to generate valid binding. Clean up the header, remove all #ifdef etc, include what those types actually should be, and then try generating code again.