How do I add `odex` files to the classpath for dalvikvm? - java

This question is a follow-up to my earlier question.
Here is the same example from that question.
import android.os.SystemClock;
/**
* Command that sends key events to the device, either by their keycode, or by
* desired character output.
*/
public class MWE {
public static void main(String[] args) {
System.out.println(SystemClock.uptimeMillis());
}
}
After I looked around in my /system/framework directory, I discovered that the class android.os.SystemClock is defined in framework.odex on my phone. I naturally tried the following two command to try to access it.
/system/bin/dalvikvm -Xbootclasspath:/system/framework/core.jar -classpath /system/framework/framework.odex:/data/local/tmp/MWE.jar MWE
/system/bin/dalvikvm -Xbootclasspath:/system/framework/core.jar:/system/framework/framework.odex -classpath /data/local/tmp/MWE.jar MWE
However, both of them resulted in the same error message about not being able to find the class definition.
How do I add such odex files to the classpath for dalvikvm?

Have you tried just:
/system/bin/dalvikvm -classpath /data/local/tmp/MWE.jar MWE
As far as I know, in this case it will pull in the boot classpath from the BOOTCLASSPATH environment variable, which should already contain core.jar and framework.jar.
However, I suspect that will actually result in an UnsatisfiedLinkError exception, because the JNI library that implements some of the native methods in SystemClock won't be loaded.
In that case, there's a handy utility class available that should load the native libraries.
dalvikvm -classpath /data/local/tmp/MWE.jar com.android.internal.util.WithFramework MWE

Related

Python Jpype can't see Java classes in JAR file

I am trying to work through what should be a simple problem, but am missing something. I have a very simple Java class:
package blah.blah;
public class Tester {
public String testMethod1() { return "GotHere"; }
public String testMethod2() { return "GotHereToo"; }
} // Tester
I am trying to get it to load into JPype:
import jpype
import jpype.imports
from jpype.types import *
path_to_jvm = "C:\\Java\\OracleJDK-8_241_x64\\jre\\bin\\server\\jvm.dll"
jpype.startJVM(path_to_jvm, classpath=["C:\\Users\\Administrator\\eclipse-workspace\\JpypeTest\\src;"])
from java.lang import System
print(System.getProperty("java.class.path"))
from java.io import ObjectInputStream
from blah.blah import Tester
tester = Tester()
print(tester.testMethod1())
print(tester.testMethod2())
jpype.shutdownJVM()
Everything works fine when I load the class directly using the above code. It stops working when I try to get it to load the Class file via a JAR.
jpype.startJVM(path_to_jvm, classpath=["C:\\Users\\Administrator\\JpypeTest.jar;"])
The error I get is:
Traceback (most recent call last):
File ".\jpype_test.py", line 16, in <module>
from blah.blah import Tester
ModuleNotFoundError: No module named 'blah'
PS C:\Users\Administrator> python .\jpype_test.py
C:\Users\Administrator\JpypeTest.jar;
Traceback (most recent call last):
File ".\jpype_test.py", line 16, in <module>
from blah.blah import Tester
ModuleNotFoundError: No module named 'blah'
I have built the JAR file a few different ways from Eclipse 2020/09 using JAR export and from the command line using:
C:\Users\Administrator\eclipse-workspace\JpypeTest\src>"C:\Java\OracleJDK-8_241_x64\bin"\jar cf C:\Users\Administrator\JpypeTest.jar blah\blah\*.class
I have confirmed that the JVM and the python interpreter are both 64 bit. I have also done my best to ensure the JVM is exactly the same between Eclipse, the command line and Python.
From what I can see, the JAR looks fine regardless of how I build it. It contains the blah\blah directory and the Tester.class file under it. The manifest is the only other file in the JAR.
I have also tried creating the JAR file with the class file at different directory levels (ie. one level of blah directories and no levels of blah directory).
Here are the versions of the python software:
Python 3.8.5 (default, Sep 3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Package Version
------------ -------------------
certifi 2020.6.20
JPype1 1.0.2
pip 20.2.3
setuptools 50.3.0.post20201006
wheel 0.35.1
wincertstore 0.2
I clearly have the base plumbing working since it can see the class file. Any thoughts on why the JAR is failing?
Thanks a bunch for your consideration.
Check that you don't have a directory called "blah" that python would look in for modules. This would hide your Java classes, as per https://jpype.readthedocs.io/en/latest/userguide.html#importing-java-classes :
One important caveat when dealing with importing Java modules. Python always imports local directories as modules before calling the Java importer. So any directory named java, com, or org will hide corresponding Java package. We recommend against naming directories as java or top level domain.

Jar Class not found upon execution

I am trying to use the javax.jms library: https://docs.oracle.com/javaee/7/api/javax/jms/package-summary.html, for which I have downloaded the jar: http://www.java2s.com/Code/Jar/j/Downloadjavaxjms111sourcesjar.htm
Specifically, I am trying to use the MessageListener and Message classes, which I know to be in there based on the Jar decompilation. I put this jar file next to my java file, so that the file structure looks like this:
myDir
-|jms.jar
-|Main.java
Main.java:
import javax.jms.MessageListener;
import javax.jms.Message;
public class Main {
public static void main(String[] args) {
MessageListener listener = new MessageListener() {
#Override
public void onMessage(Message msg) {
}
};
System.out.println("Hello World");
}
}
I can compile this using javac -cp jms.jar Main.java from inside myDir. This creates Main.class. However, when I run java Main, I get:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/jms/MessageListener
This would lead me to believe that MessageListener is not included in the jar, but it is and the file structure is javax/jms/MessageListener checks out. What dumb mistake am I making?
When I compile without -cp js, it fails, saying:
error: package javax.jms does not exist
thus, at least the compiler is looking in the jar.
I made 2 Mistakes
1: Credit to #NormR, .:jms.jar (or .; for Windows I surmise)
2: Link jar while executing. Therefore, the commands should've been:
javac -cp .:jms.jar Main.java
java -cp .:jms.jar Main

Is there any limitation on the length of the classpath in java?

I tried to set classpath from command line for a java class
java -cp lib1.jar;lib2.jar;lib3.jar MyProgram
The above code threw runtime exception as it has further dependency with other jar file when I added the jar file it is unable to recognize the Main class in MyProgram class and threw
Error:Main method not found in class MyProgram,please define the method as public static void main(Stirng[] args)
The length of the strings lib1 ,lib2 and lib3 is about 400 characters.
Is there any limitation on the size of the classpath which can be set from command line .I tried setting class path using Manifest file as well but still it is throwing same exception.
I cannot test the program that you have written,so one solution by observing the details provided could be-
java –classpath ${CLASSPATH} MyProgram
Note: here you would have to set CLASSPATH variable before using it.

ANTLR Ubuntu Java Makefile

Ive been trying to test a simple project written by some students. Im testing it on Ubuntu and the project requires me to use ANTLR and a Makefile.
It has been a nightmare to find a configuration of makefile, files and folders that compiles and executes successfully.
So basically this is the folder/file setup:
Makefile
test.txt
laboratorio/
lab02/
Main.java
Lab02.g
The contents of Main.java are fairly simple. They just read the grammar token by token:
package laboratorios.lab02;
import org.antlr.v4.runtime.*;
public class Main{
public static void main(String[] args) throws Exception{
try{
Lab02 lexer = new Lab02(new ANTLRFileStream(args[0]));
while (lexer.nextToken().getType() != Token.EOF);
}catch(ArrayIndexOutOfBoundsException aiobe){
System.err.println("Must provide a valid path to the filename with the tokens");
System.exit(1);
}catch(Exception e){
System.err.println("Must provide a valid path to the filename with the tokens");
System.exit(1);
}
}
}
The contents of Lab02.g (the grammar) are irrelevant for the problem, but it produces a Lab02.java file (with package laboratorios.lab02) that must be compiled and referenced by the Main.java file.
The problem came when trying to test the makefile on Ubuntu. With every configuration I tried I kept getting errors (when compiling or running the Main java file) like:
java.lang.NoClassDefFoundError: org/antlr/v4/runtime/CharStream
Could not find or load main class org.antlr.v4.Tool
Error: Could not find or load main class
Ive followed the exact steps of this tutorial to set up antlr on my pc: Getting Started with ANTLR v4
After many unsuccessful attempts I arrived at this magical configuration that made the whole project work nicely.
Makefile:
make: gramatica main
gramatica: laboratorios/lab02/Lab02.g
java org.antlr.v4.Tool laboratorios/lab02/Lab02.g
main: laboratorios/lab02/Lab02.java laboratorios/lab02/Main.java
javac laboratorios/lab02/Lab02.java laboratorios/lab02/Main.java
run: laboratorios/lab02/Main.class
java -cp ${CLASSPATH}:Lab02.class laboratorios/lab02/Main test.txt
clean:
rm -rf laboratorios/lab02/*.tokens
rm -rf laboratorios/lab02/*.class
rm -rf laboratorios/lab02/Lab02.java
rm -rf laboratorios/lab02/*~
I required me to set the CLASSPATH in the bashrc like this:
export CLASSPATH=.:~/your/path/to/antlr/antlr-4.2-complete.jar
As you would find in the tutorial I previously mentioned (Getting Started with ANTLR v4), it says you should write the Classpath using quotes. COMPLETELY IGNORE THAT ADVICE! Whenever I used quotes the main class wouldnt run as ANTLR was 'missing'. Also, the aliases in the tutorial are completely optional.
Some other things worth pointing out are that placing the Makefile inside the laboratorio/lab02/ folder was not helping either. Moving it out and referencing the java files from the outside helped A LOT. And the characters ".:" helped to execute the Main class as it would say it couldn't been found.

Error looking up function 'HelloWorld': The specified procedure could not be found

I am trying to access a VB .NET dll method that I have made in my java code.
I am trying to achieve this using JNA.
Here's my Java code.
Hello.java (invokes the dll method)
import com.sun.jna.Native;
public class Hello {
public static void main(String[] args) {
String myPath = System.getProperty("user.dir");
System.setProperty("java.library.path", myPath);
NativeInterface nInterface = (NativeInterface) Native.loadLibrary(
"SampleDLLProject", NativeInterface.class);
nInterface.HelloWorld();
}
}
And here's the interface
NativeInterface.java
import com.sun.jna.*;
public interface NativeInterface extends com.sun.jna.Library {
public void HelloWorld();
}
The error that I am facing is:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'HelloWorld': The specified procedure could not be found.
at com.sun.jna.Function.(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 $Proxy0.HelloWorld(Unknown Source)
at Hello.main(Hello.java:10)
Also I checked the dll for any kind of discrepancy using ildasm.
There is no difference between the method name present in dll and name in Hello.java.
Interestingly, I tried to test the code for the puts() method of windows dll msvcrt.dll and it works perfectly fine. So the problem is for the DOT NET dlls .
Please help!
The library you are using is for loading methods from native libraries (such a windows.dll and msvcrt.dll), these libraries are compiled into native code that can run directly on x86 or x64 processors.
Libraries created in VB.NET are not native libraries, they are CLI (Common Language Infrastructure) Assemblies that are compiled into CIL (Common Intermediate Language) which is then compiled on the fly to run any kind of processor (just like Java!)

Categories