Class not found by FindClass - java-native-interface

I have some troubles with a non-working call to FindClass in my application. I've looked up many questions on this subject but none of these solved my problem...
The JVM creation code:
JavaVM *test_jvm;
JNIEnv *test_jenv;
JavaVMInitArgs vm_args; /* JDK 1.1 VM initialization arguments */
JNI_GetDefaultJavaVMInitArgs(&vm_args);
JavaVMOption options[1];
options[0].optionString = classpath;
vm_args.version = JNI_VERSION_1_4; /* New in 1.1.2: VM version */
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
jint ret = JNI_CreateJavaVM(&test_jvm, reinterpret_cast<void**>(&test_jenv), &vm_args);
assert(ret == JNI_OK);
assert(test_jenv->FindClass("my/package/MyClass") != 0);
The definition of classpath:
char classpath[] = "-Djava.class.path=lib/somejar1.jar:"
"bin:"
"lib/somejar2.jar:"
"lib/somejar3.jar";
When I run this code, the assert() code fails, but when I run this (at the same location):
java -cp lib/somejar1.jar:bin:lib/somejar2.jar:lib/somejar3.jar my.package.MyClass
...everything works fine.
The class I am loading is very simple:
package my.package;
public class MyClass {
public static void main(String[] args) {
System.out.println("Hello World!");
}
};
I also tried without the main method but the result was the same. I can load classes from the JARs without issues, but I cannot load this one class from the bin directory...
I have checked many questions, but most of these were about incorrect classpath or incorrect naming convention... I double checked everything and I did not find any issue.
Some other answers mentioned problem with threads, but since I am creating the JVM from a C++ environment, I don't if this apply? And even if it does, this call to FindClass should not be problematic?
I would really appreciate a solution to this, or at least a way to debug in more depth what is happening...

Disclaimer: I found the root of the problem, and I am writting this answer because I did not find a canonical one for FindClass-related problem.
The issue was a difference between the java version of the javac executable used to compile the .java file (Java 1.7, standard Java installation on the machine) and the version of the JNI code (OpenJDK 1.5, custom installation).
Once I compiled the java files with the correct javac executable, the code worked without issue.

Related

JVM can't find class when using JNI from C++

I'm trying to call JAVA methods from C++ by JNI. First of all, I got this example, tried it out. I changed the path of JDK and after that I could run the examples and they properly worked.
After that, I tried to import my own JAR file and use one class from it. I copied the code from the example and replaced the classpath and classname with my own:
void MyCPPClass::CallJava()
{
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
JNIEnv *env; // Pointer to native interface
//==================== prepare loading of Java VM ============================
JavaVMInitArgs vm_args; // Initialization arguments
JavaVMOption* options = new JavaVMOption[ 1 ]; // JVM invocation options
options[ 0 ].optionString = "-Djava.class.path=MyJar.jar"; // where to find java .class
vm_args.version = JNI_VERSION_1_8; // minimum Java version
vm_args.nOptions = 1; // number of options
vm_args.options = options;
vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail
//================= load and initialize Java VM and JNI interface ===============
jint rc = JNI_CreateJavaVM( &jvm, (void**)&env, &vm_args ); // YES !!
delete options; // we then no longer need the initialisation options.
//========================= analyse errors if any ==============================
// if process interuped before error is returned, it's because jvm.dll can't be
// found, i.e. its directory is not in the PATH.
if( rc != JNI_OK )
{
exit( EXIT_FAILURE );
}
jclass cls1 = env->FindClass( "aaa/bbb/MyClass" );
...
}
The JAR contains only one class aaa.bbb.MyClass and it's made with IntelliJ IDEA and mvn package command. I copied the JAR file next to my executable.
A value of rc is always 0 (JNI_OK), but the value of cls1 is always NULL. I think that JVM can find the JAR, because when I'm debugging I can't delete the JAR after FindClass.
The JAR file contains the MyClass.class file, I checked it.
I have checked some previous questions ( 1, 2, 3 and some others) yet, but I couldn't get where I made a mistake.
UPDATE: I tried to copy the MyClass.class file and MyJar.jar file into the directory of the example linked before, and JVM can't find MyClass. It's possible that something missing from my java source file? The package declaration is correct.
What can cause that JVM can't find MyClass?
Moved solution from question to answer:
SOLUTION: I had to add the maven dependencies' JARs to the classpath. Now it works!

Building RakNet C# Wrapper with Swig, get an annoying error at build

I know I should post this on the official RakNet forum, but I actually have, but it seems to be dead as hell.
The reason why I'm asking here is because I have no idea of C++, I'm a game developer and we're using Unity3D/C# to develop our new game, it's going to be Multiplayer and as RakNet was Open Sourced I wanted to give it a try.
So, here we go, this is the error log:
raknet_wrap.cxx(15441): error C2558: class 'RakNet::ReliabilityLayer' : no copy constructor available or copy constructor is declared 'explicit'
And the line where the error is is this:
jresult = new ReliabilityLayer((const ReliabilityLayer &)result);
Full function:
SWIGEXPORT void * SWIGSTDCALL CSharp_RakPeer_RemoteSystemStruct_reliabilityLayer_get(void * jarg1) {
void * jresult ;
RakNet::RakPeer::RemoteSystemStruct *arg1 = (RakNet::RakPeer::RemoteSystemStruct *) 0 ;
ReliabilityLayer result;
arg1 = (RakNet::RakPeer::RemoteSystemStruct *)jarg1;
result = ((arg1)->reliabilityLayer);
jresult = new ReliabilityLayer((const ReliabilityLayer &)result);
return jresult;
}
Can someone tell me why is it not working and explain it for a completely new person to C++ so I can understand the error?
(Edit) Going to also provide the ReliabilityLayer class! Here it is: http://pastebin.com/qTXedJFw
So I finally managed to build the RakNet C# DLL of the newest RakNet version.
And, as I don't want anybody with no experience on C++ to go through the madness I did through, I'm just sharing the DLL for easy use. Just import it to your project and start using it.
Here it is: https://drive.google.com/file/d/0BwuOJwLuDZfnM29DTFlLTWZWOXc/view?usp=sharing
OK to whoever is watching this and doesn't have a successful answer.
This is clearly a compiler bug in MSVC 2013 (that's what I tried).
SWIG generates the file 'RakNet_wrap.cxx' with the following line:
jresult = new ReliabilityLayer((const ReliabilityLayer &)result);
The quickest way around it is to edit this line so that it reads:
jresult = new ReliabilityLayer(result);
and hence the casting becomes implicit instead of explicit and MSVC 2013 accepts this.
The only problem is that when you hit Build, SWIG will overwrite this file and introduce the error again. So just remove the SWIG prebuild step (Alt+F7->Build Events->Pre-Build Event remove the PreBuild.bat from the command line) and build again. Now it will successfully compile and link as it should.
Don't forget to put the PreBuild.bat file again if you need to modify the source code and run SWIG again!
Also use SWIG 2.0.12; the latest version I tried (3.0.5); generates broken C# code (undefined HandleRef and IntPtr because System.Runtime.InteropServices is not either explicit nor imported via 'using' keyword).
I've raised a ticket to the SWIG project about this: https://github.com/swig/swig/issues/433

Embedding clang Compiler into OS X Cocoa App

As part of development for an application of mine that generates C source code, I need to be able to embed a compiler into my application so that it can generate executable object code. Since this is a sandboxed app intended for the Mac App Store, I cannot use NSTask to directly invoke clang, as the standalone tool apparently does not work under a sandbox. Pity.
I came across libclang, a library version of the compiler, which seems to do the trick. Using information from here, I was able to grab a preconfigured libclang binary to integrate into my application. Trouble is, I can't seem to figure out what the libclang API calls are that process and generate an executable. I found this sample code:
string source = "app.c";
string target= "app";
llvm::sys::Path clangPath = llvm::sys::Program::FindProgramByName("clang");
// arguments
vector<const char *> args;
args.push_back(clangPath.c_str());
args.push_back(source.c_str());
args.push_back("-l");
args.push_back("curl");
clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions());
clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
clang::DiagnosticsEngine Diags(DiagID, DiagClient);
clang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), target, true, Diags);
clang::OwningPtr<clang::driver::Compilation> c(TheDriver.BuildCompilation(args));
int res = 0;
const clang::driver::Command *FailingCommand = 0;
if (c) res = TheDriver.ExecuteCompilation(*c, FailingCommand);
if (res < 0) TheDriver.generateCompilationDiagnostics(*c, FailingCommand);
Unfortunately, though, it won't compile. I get these errors:
Maybe I'm not including the right header files, I don't know. But given the lack off documentation for libclang, I would very much appreciate some help.

Why do I receive a SIGSEGV signal while using the Aria robotics API?

I am using the Aria C++ programming libs for mobile robots (http://robots.mobilerobots.com/wiki/ARIA). I am new to this API so I wanted to start with a simple action class derived from ArAction. Now I tried to develop a small test program (an ArAction) in order to
control a simulated p3dx robot via MobileSim. Development takes place under Ubuntu 10.10, using gcc 4.4.5. Making (compiling) my code works fine, without errors. I can also set the desired speed for example in my ArAction's fire() method, and the simulation is also working as desired.
But, unfortunately, I can't use the ArRobot object attached to the ArAction I am overriding. The problem is that none of the member functions of the ArRobot object seems to work. For example, calling getVel() or getCompass() always returns a zero value. And when I call the hasFrontBumpers() method the program even crashes with the error message "Aria: Received signal 'SIGSEGV'. Exiting.". As soon as I remove this method call and recompile the error is also gone again...
Here is the relevant code that leads to the crash:
ArActionDesired * forward::fire(ArActionDesired d)
{
desiredState.reset();
ArRobot *r = getRobot();
if(r == NULL)
{
printf("ArRobot = NULL\n");
deactivate();
return &desiredState;
}
printf("ok, ArRobot is not NULL, check for bumpers...\n");
r->hasFrontBumpers(); // <-- this leads to the SIGSEV-based "crash"
return &desiredState;
}
Any ideas what I am missing here -- is it a problem with my coding, or with the simulation environment? Thanks in advance for your help!
Kind regards, Matthias
ok, found it out now -- for the records: the Aria libs in version 2.7.2 are based on gcc-3 and libstdc++ 5, but Ubuntu 10.10 (which I am using) is shipped with gcc-4 and libstdc++ 6 per default. So I had to manually install the older versions of both packages, now my code is running fine...
cheers!
Calling hasFrontBumpers() for a p3dx from the fire() works fine for me on a similar Linux platform. If something is wrong, it is not in this method but in the initialization of the system. A reason for the non-moving robot could be that robot.enableMotors() hasn't been called.

C++\IronPython integration example code?

I'm looking for a simple example code for C++\IronPython integration, i.e. embedding python code inside a C++, or better yet, Visual C++ program.
The example code should include: how to share objects between the languages, how to call functions\methods back and forth etc...
Also, an explicit setup procedure would help too. (How to include the Python runtime dll in Visual Studio etc...)
I've found a nice example for C#\IronPython here, but couldn't find C++\IronPython example code.
UPDATE - I've written a more generic example (plus a link to a zip file containing the entire VS2008 project) as entry on my blog here.
Sorry, I am so late to the game, but here is how I have integrated IronPython into a C++/cli app in Visual Studio 2008 - .net 3.5. (actually mixed mode app with C/C++)
I write add-ons for a map making applicaiton written in Assembly. The API is exposed so that C/C++ add-ons can be written. I mix C/C++ with C++/cli. Some of the elements from this example are from the API (such as XPCALL and CmdEnd() - please just ignore them)
///////////////////////////////////////////////////////////////////////
void XPCALL PythonCmd2(int Result, int Result1, int Result2)
{
if(Result==X_OK)
{
try
{
String^ filename = gcnew String(txtFileName);
String^ path = Assembly::GetExecutingAssembly()->Location;
ScriptEngine^ engine = Python::CreateEngine();
ScriptScope^ scope = engine->CreateScope();
ScriptSource^ source = engine->CreateScriptSourceFromFile(String::Concat(Path::GetDirectoryName(path), "\\scripts\\", filename + ".py"));
scope->SetVariable("DrawingList", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingList::typeid));
scope->SetVariable("DrawingElement", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingElement::typeid));
scope->SetVariable("DrawingPath", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingPath::typeid));
scope->SetVariable("Node", DynamicHelpers::GetPythonTypeFromType(AddIn::Node::typeid));
source->Execute(scope);
}
catch(Exception ^e)
{
Console::WriteLine(e->ToString());
CmdEnd();
}
}
else
{
CmdEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
As you can see, I expose to IronPython some objects (DrawingList, DrawingElement, DrawingPath & Node). These objects are C++/cli objects that I created to expose "things" to IronPython.
When the C++/cli source->Execute(scope) line is called, the only python line
to run is the DrawingList.RequestData.
RequestData takes a delegate and a data type.
When the C++/cli code is done, it calls the delegate pointing to the
function "diamond"
In the function diamond it retrieves the requested data with the call to
DrawingList.RequestedValue() The call to DrawingList.AddElement(dp) adds the
new element to the Applications visual Database.
And lastly the call to DrawingList.EndCommand() tells the FastCAD engine to
clean up and end the running of the plugin.
import clr
def diamond(Result1, Result2, Result3):
if(Result1 == 0):
dp = DrawingPath()
dp.drawingStuff.EntityColor = 2
dp.drawingStuff.SecondEntityColor = 2
n = DrawingList.RequestedValue()
dp.Nodes.Add(Node(n.X-50,n.Y+25))
dp.Nodes.Add(Node(n.X-25,n.Y+50))
dp.Nodes.Add(Node(n.X+25,n.Y+50))
dp.Nodes.Add(Node(n.X+50,n.Y+25))
dp.Nodes.Add(Node(n.X,n.Y-40))
DrawingList.AddElement(dp)
DrawingList.EndCommand()
DrawingList.RequestData(diamond, DrawingList.RequestType.PointType)
I hope this is what you were looking for.
If you don't need .NET functionality, you could rely on embedding Python instead of IronPython. See Python's documentation on Embedding Python in Another Application for more info and an example. If you don't mind being dependent on BOOST, you could try out its Python integration library.