I am helping to code a stop-motion program that is to be cross platform, and on windows it works great. For those who do not know, stop motion is just a fancy term for animation. This program allows users to plug in Nikons, Canons, and Webcams into the computer, and have the program display a live view of the scene, and then have the ability to manually control the camera from there. Included is a framework file from canon for the camera, with a path defined as shown
import com.sun.jna.Native;
initialization and such
public static EdSdkLibrary EDSDK = (EdSdkLibrary) Native.loadLibrary("Macintosh/EDSDK.framework/EDSDK",EdSdkLibrary.class, options);
The error is thrown at the "public static int..." saying that the image is not found. I have tried numerous times redefining the path, moving the framework, and using various other frameworks identical to the one I'm using. Remember, this works flawlessly on Windows, but on Mac there is a problem.
Are frameworks different on macs, or are they to be defined differently? I have looked and found no other solutions.
EDIT: Okay, I defined the path and it now has this symbol > with no text next to it. WHat do I do now?
EDIT: It is saying that this % is not a command. Without it, it still fails to work.
JNA will successively attempt to load frameworks from ~/Library/Frameworks, /Library/Frameworks, and /System/Library/Frameworks, based on the core framework name (EDSDK in this case).
If the loadLibrary call succeeds, then the library was found. If the library was not found, you'll get an UnsatisfiedLinkError.
Frameworks are basically bundles of a shared library with other resources; ESDK.framework/ESDK is the actual shared library (for frameworks, OSX omits the "dyld" suffix normally found on a shared library on OSX).
EDIT
Here's how to make a symlink so that the paths look more like what JNA is expecting. From a terminal (run Terminal.app):
% ln -s /your/complete/path/to/Macintosh/EDSDK.framework ~/Library/Frameworks/EDSDK.framework
When this is done successfully, you should see the following when listing (ls) the symlink:
% ls -l ~/Library/Frameworks/EDSDK.framework
lrwxrwxr-x 1 YOU YOU 50 Mar 31 01:13 /Users/YOU/Library/Frameworks/EDSDK.framework -> /your/complete/path/to/Macintosh/EDSDK/Framework/EDSDK.framework
You should see the symlink path (where JNA will look) on the left, with the path to the real file on the right. If not, delete the symlink file and try again. Note that you may need to create the directory ~/Library/Frameworks first; it may not yet exist.
Finally, make sure that the library you're trying to load matches the VM you're trying to load with; 64-bit with 64-bit, 32-bit with 32-bit. Canon does not provide a universal binary of their library, so you'll need to point to one or the other or merge the two using lipo.
Not really an answer, but more information on the same problem, which I'm experiencing myself.
I can add that JNA will find my frameworks if they're in one of the standard public locations an executable looks for its frameworks, i.e.
~/Library/Frameworks - (public frameworks for the use of the current user)
/Library/Frameworks - (public frameworks for the use of any user)
/System/Library/Frameworks - (public system frameworks)
However, If I want my custom framework to be private - i.e. - not discoverable to other processes than my java vm -- then for some reason JNA doesn't do it.
I know MacOS dynamic loader, when trying to locate a library/framework for any normal (native) MacOS process, does NOT start searching the above locations, but first within several standard "private" locations: (also known as rpath search-path)
in the "Frameworks" directory at the same location as the binary from which the process was loaded: e.g. path/to/my/binary/Frameworks/mySDK.framework
in the "Frameworks" directory at the place where dynamic loader loaded the process (in Application bundles, that would be the myApp.app/Contents/Frameworks/mySDK.framework folder.
So, you can usually create a 'Frameworks' directory of your own right next to your binary, and place your framework in it.
However - JNA misses that. I tried to create a "Frameworks" directory within the "Zulu" - in zulu-11.jre/Contents/Home/bin right next to the 'java' binary, and in other places - but JNA won't find in any of them.
I wonder why, and if there is any documentation for that.
The trick of installing a symlink to my custom framework in /Library/Frameworks may serve you, but I cannot allow other processes to find or load my framework.
Related
I have inserted some new functionality in the Android Runtime (ART), and now I want to expose it to the outside world via an interface. As it is native code, I will be using the JNI interface to call this new functionality, in a similar way with the Garbage Collector functionality: Runtime.getInstance().gc().
However, I don't care in building a new SDK that could be used by an IDE, as I will be manually injecting bytecode to .dex files that will make the call.
I have edited the Runtime.java in libcore/luni, and java_lang_Runtime.cc in art in a similar way with the gc() function. I am generating the new libart.so and core-libart.jar and I flash them on a device.
However, when I try to reboot the device, I get the message:
Failed to register native method java.lang.Runtime.myMethod()V in /system/framework/core-libart.jar
...
----- class 'Ljava/lang/Runtime;' cl=0x0 -----
vtable (24 entries, 11 in super):
// 24 entries are listed here. My entry is missing.
...
In the Runtime.java I register the native method and supress some warnings on a full build using #hide. eg,
/** #hide */
public native void myMethod();
In the java_lang_Runtime.cc, I define the function (that will call the ART internal stuff) and register it to the gMethods[] array using a macro. eg,
static void Runtime_myMethod(JNIEnv*, jclass) {
// body
}
NATIVE_METHOD(Runtime, myMethod, "()V")
The device is on a bootloop. Are there any other files that I should have edited? Should I build extra modules, or send any other files on the device?
BTW, I do NOT want to build a new SDK as for calling myMethod I will inject Dalvik bytecode to an APK file. Basically I will get the Runtime instance, and then call the method.
The problem:
Android ships the factory images with framework components being pre-optimised.
The file boot.oat contains pre-optimised code (or odex code), which can be accessed by reading pointers contained in the boot.art file.
These two files contain code only for the boot classpath.
The rest of the framework, and the rest of the system applications (in app and priv-app) folders have standalone odex files.
During this pre-optimisation phase, the dex code is taken out of a framework module (a jar, or an apk), is compiled using dex2oat, and the resulting code resides in the files I just mentioned.
Some of the things I 've tried:
Shipping just the libart.so and core-libart.jar does not work, even though the latter contains the dex code. This is because the runtime is still attempting to read that information from boot.oat.
By modifying the device configuration to do the pre-optimisation, the aosp build system can generate boot.oat|art and the rest of the odex files (more here). I expected that flashing all these should work, but it didn't.
(at least for the marshmallow-release branch, on a nexus6)
I 've tried flashing the whole aosp-generated build, and it didn't work, even with a custom kernel that I 've build with the security features (verity) disabled.
I am sure that some of these should have worked, but there must be something else that should be considered during building the OS.
Solution:
The last resort, was deodexing and thankfully it worked.
I have written a small script that does it for the Nexus 6 on Marshmallow.
The script, during a 1st stage, it takes out all the oat/odex code from relevant places, and de-optimises it to dex code, thanks to the oat2dex and smali projects.
On a 2nd stage, it packs the dex code back, in the framework modules (jars/apks).
Shipping a whole new core-libart.jar to the device still does not work (not sure why), but tinkering the dex files before packing them into the modules does the trick! :))
The libart.so can now find Runtime.myMethod(), which can be invoked by an application (smali tinkering again) to run my code inside ART.
When I build my Xamarin project the version of the jarsigner tool it uses is ALWAYS from \Java\jdk1.6.0_39\bin\
I was wondering if we could change to different version of JDK.
Looking at the build output it seems to boil down to whatecer MSBuild../Xamerin/Android.Build.Tasks.dll tells it.... (see below)
Is there a way to get the build to point to another path...a later version of the JDK?whatever
11>Using "AndroidSignPackage" task from assembly "C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Build.Tasks.dll".
11>Task "AndroidSignPackage"
11> C:\Program Files (x86)\Java\jdk1.6.0_39\\bin\jarsigner.exe
Looking at the Xamarin's Custom MSBuild Task Library (C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Build.Tasks.dll) AndroidSignPackage extends AndroidToolTask which extends the built in ToolTask class. It also looks like they properly implemented it as well so you should be able to simply pass the additional optional parameter ToolPath.
If you're calling the task directly from MSBuild as part of a custom build process the command might looks like this:
<AndroidSignPackage
UnsignedApk="pathtounsignedapk"
SignedApkDirectory="signedapkoutputdir"
Keystore="yourkeystorelocation"
KeyAlias="thekeyaliasusedtosign"
StorePass="thepasswordforthekeystore"
ToolPath="NEWPATHTOJAVASDK" />
If you're trying to do this integrated within the Visual Studio Environment you'll need to start groveling around in their *.Targets file and chase it down, if you're not comfortable with MSBuild I do not recommend doing so.
BEYOND THIS POINT NO WARRANTY GROVELING IN UNDOCUMENTED LAND COULD AND WILL BREAK AT THE LEAST OPPORTUNE TIME AS PER MURPHY
In my version of the Xamarin Toolchain in Xamarin.Android.Common.targets (C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets) we see that the AndroidSignPackage is called from within the _Sign target, it appears that, at least in this version, are passing the ToolPath attribute, which in this version is defined as $(JarsignerToolPath), looking further up in the .targets file we see that this is defined as follows:
<CreateProperty Value="$(_JavaSdkDirectory)\bin">
<Output TaskParameter="Value" PropertyName="JarsignerToolPath"
Condition="'$(JarsignerToolPath)' == ''"
/>
</CreateProperty>
It looks like they were really nice (at least in this version) at validate that $(JarsignerToolPath) is not defined prior to setting this value, if it is this task will not do anything and take the existing value.
At this point in time you have a couple of options, what it boils down to is they'll respect the MSBuild Property $(JarsignerToolPath) however it comes in before this build process. If you read the documentation on MSBuild you'll see that you can define that property in a couple of ways.
The most popular (and my recommendation) is to declare it straight up in your MSBuild Script (remember that CSPROJ files are just MSBuild Scripts) in one of the property groups (I'd recommend under a build configuration) you can simply define this property explicitly for example:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|JDK17' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
... (Additional properties trimmed) ...
<JarsignerToolPath>C:\Program Files (x86)\Java\jdk1.7.0_71\bin</JarsignerToolPath>
</PropertyGroup>
Alternatively you can set an Environment variable prior to launching Visual Studio/MSBuild process performing the build that sets the JarsignerToolPath to the correct property.
Obviously you can use the above knowledge to take it even further and look to research if you could replace $(_JavaSdkDirectory)...
Update: The problem was solved with the help of MathWorks. I've published the answer below.
I need to control a program (Zemax) from Matlab. Unfortunately, Zemax only supports DDE for such control, which Matlab does not support any more. It works, but stops working on 64 bit platform after a few (presumable 63) DDE calls.
I wonder if there are working solutions. I could probably program a DLL with correct DDE support and then use DDE in Matlab via this DLL. This is a major effort for me. A more suitable solution would be to use Java DDE methods. Following another post here, I've discovered the JDDE library. However I cannot make it work: Even if I am in the directory with the DLL and JAR files, executing
import pretty-tools.JDDE-2.0.3.*
works fine but calling
a = com.pretty_tools.dde.client.DDEClientConversation()
afterwards (as done here) results in
Undefined variable "com" or class "com.pretty_tools.dde.client.DDEClientConversation".
I have very limited writing privileges on my PC, so I have added the javaclasspath.txt file with the jar/dll location to the directory indicated by prefdir. The file looks like this:
C:\Users\xxxxxxxx\Documents\matlab toolbox\jdde\pretty-tools-JDDE-2.0.3.jar
Calling javaclasspath shows a long listing with the last lines being:
...
C:\Program Files\MATLAB\R2012b\java\jarext\webservices\ws_client_core\mw-service-client-core.jar
C:\Users\kkarapet\Documents\matlab toolbox\jdde\pretty-tools-JDDE-2.0.3.jar
DYNAMIC JAVA PATH
<empty>
So path seems to be set correctly. What am I doing wrong?
With the help of MathWorks support, I've found the answer. Here is how to make JDDE work with Matlab 2012b, without admin privileges:
Download and unpack JDDE files (DLLs and JAR) into some folder. Let's say it's $path-to-jdde$\.
In Matlab, type prefdir. Open the resulting directory and create two files there, javaclasspath.txt and javalibrarypath.txt.
In javaclasspath.txt, add $path-to-jdde$\pretty-tools-JDDE-2.0.3.jar.
In javalibrarypath.txt, add $path-to-jdde$\.
Restart Matlab.
Now call ddeConv = com.pretty_tools.dde.client.DDEClientConversation; and start using the created object as described in JavaDoc. E.g. to connect to Zemax, run Zemax and then in call ddeConv.connect('Zemax', 'abc').
Step 2 above can only be done starting Matlab version R2012b. With an older version, if you have the write rights on the Matlab installation directory, you should be able to replace step 2 by editing the files librarypath.txt and classpath.txt in $MATLABROOT$\toolbox\local. I could not verify it so if you confirm it please let me know in the comment below.
I'm using JNA and Java but I think this question affects any native-to-nonnative bridge.
I have a Java application which relies on lib1.dylib, and lib1.dylib relies on lib2.dylib.
I want to put everything inside of my .app file on Mac. I can easily put lib1.dylib inside and set java.classpath (or NativeLibrary.addSearchPath()) to tell the JVM where to find lib1.dylib. The trouble is, I don't know how to communicate that lib1.dylib's dependencies are also in the location I provided. The result is that lib1 is loaded fine, but then lib2 can't be found since it's not in the operating system's library path.
Anyone know how I can overcome this problem? I imagine it must come up plenty in big projects with large numbers of shared libraries.
I've come across this problem before, and have just run into it again today. You may be able to get around it by adding the VM argument "-Djava.library.path=/path/to/other/libs", but I seem to remember Java only uses that to search for the intial library and then uses the system PATH to look for any dependencies.
A few solutions I've tried before:
1) Use System.load(absolutePath) on the dependent library before loading your library. Doesn't make your program ultra-portable though, unless you always know where that library is going to be.
2) In a case where lib1 depends on lib2, I actually used SetCurrentDirectory (Windows, not sure of the Mac equivalent) in the native code before it linked to any of the dependent libs, and that seemed to work. Again, requires knowing where the other libs are.
3) On Windows, could dump the dependent libraries in c:\windows\system32, and it finds them.
A few helpful posts on a similar topic (Windows-specific, but I think the problem is the same):
http://www.realityinteractive.com/rgrzywinski/archives/000219.html
http://www.velocityreviews.com/forums/t387618-jni-library-path.html
I've found a solution for MacOSX based on the idea in (2) from Stew:
Using Mac's JarBundler (or the Ant task of the same name) set the workingdirectory variable to $JAVAROOT and make sure your dylibs are in the Contents/Resources/Java part of the .app. If you do this the dynamic linker will find all the dependency dylibs because it will be the present directory. Java will also find the original dylib (the one that has all the dependencies) for the same reason.
Ant code:
<target name="package_mac_app" depends="package_jar, compile_native" description="bundle the runnable jar into a Mac Application -- requires JarBundler ANT Task">
<taskdef name="jarbundler" classname="net.sourceforge.jarbundler.JarBundler"/>
<echo message="CREATING MAC .app EXECUTABLE"/>
<jarbundler dir="${dist}"
name="${appname}"
mainclass="myPackage.myMainClass"
icon="${icon_location}"
jvmversion="1.5+"
infostring="${appname}"
shortname="${appshortname}"
bundleid="${com.mycompany.mydepartment.myprogram}"
jar="${run_jar_location}"
workingdirectory="$JAVAROOT">
<javafilelist dir="${dylib_location}" files="my-lib.dylib"/>
<javafilelist dir="${dylib_location}" files="dependent-lib.dylib"/>
</jarbundler>
</target>
I am working on a team project in Java. One requirement is that we dynamically populate a drop-down menu of all classes that implement a certain interface. New classes can be added after compile time. To accomplish this we are using reflection.
Problem: All of the drop-down menus are blank on my system. I cannot for the life of me figure out why they are not populating. All other 5 team members have it working on their system.
Things I tired that didn't work:
1) Installing most recent eclipse (galileo) because rest team was using it
2) Re-install most recent java release (jdk1.6.0-17 and jre6)
3) Check PATH and JAVA_HOME variables
Any thoughts as to what else I can try or if something I did should have solved it and didn't? It is driving me crazy.
Edit:
I should have been clearer that we are developing in a team. We are using SVN for version control and we are all running the exact same source code. I even tried checking out a fresh copy of the entire tree from SVN, but I had the same issue with reflection on my system while it worked for teammates.
The team created an executable jar and that ran on everyone's system fine except for mine. Everything worked for me except the reflection bit.
You need to debug your application. This means you have to systematically explore possible causes of the problem. Here are some things that come to mind:
Could your GUI be failing rather than reflection? What if you output with System.out.println() rather than your menu?
Is your reflection code throwing an exception, and are you ignoring it?
Is your reflection code actually being called? Toss a println() in there to be sure!
Is the test for the interface suffering from a typo or similar error that's causing it to fail? Try finding classes that implement Serializable instead!
Is your reflection test running in the main thread and trying to update your GUI? You need to use SwingUtilities.invokeAndWait to get an update to the Swing worker thread.
You're working with Eclipse; Eclipse has a fantastic debugger. Set a breakpoint near where your main action is and then single step through the code.
PATH and JAVA_HOME won't help. PATH only affects dynamically-linked libraries ("native code"). JAVA_HOME is a scripting variable that happens to be used by some Java-based utilities like Ant and Tomcat; it means nothing to the Java runtime itself.
You need to be investigating the classpath, which should be specified by the -classpath option to the java command, in the Build Path in your Eclipse project properties, or in the Class-Path attribute of the main section of a JAR file if you're launching java with the -jar option.
From within your code, you should be able to list the contents of your classpath by examining the system property, "java.class.path"
System.out.println(System.getProperty("java.class.path"));
Problem solution:
Classpath leading to source code must have no spaces in it.
I am running windows XP and, for whatever reason, if the classpath that leads to the jar file or source code that is using reflection has any spaces in it, then the reflection fails.
I took the jar file that works for the rest of my team and ran it from C:\ on my system and the reflection worked perfectly fine.
I do not know why this is so please comment if you know what is happening.
Might be a long shot, but look for differences in security settings for you and your team mates. Article describing more details http://www.ibm.com/developerworks/library/j-dyn0603/ heading "Security and reflection"