I am instrumenting Android applications using a helper class following the example for Java instrumentation in http://www.sable.mcgill.ca/soot/tutorial/profiler2/profiler2.html.
In my BodyTransformer, I have a static block to load MyCounter class
counterClass = Scene.v().loadClassAndSupport("MyCounter");
Since Soot.Main.main(args) that processes my args (in which I provide -android-jars) is not executed while it is loading MyCounter, Soot cannot find my android jar and gives the error:
Caused by: java.lang.RuntimeException: You are analyzing an Android application but did not define android.jar. Options -android-jars or -force-android-jar should be used.
at soot.Scene.defaultClassPath(Scene.java:455)
at soot.Scene.getSootClassPath(Scene.java:224)
at soot.SootResolver.<init>(SootResolver.java:81)
at soot.Singletons.soot_SootResolver(Singletons.java:802)
at soot.SootResolver.v(SootResolver.java:91)
at soot.Scene.loadClass(Scene.java:667)
at soot.Scene.loadClassAndSupport(Scene.java:653)
at MyBodyTransformer.<clinit>(MyBodyTransformer.java:26)
... 1 more
As a solution, I provided my command line arguments (android jars, soot classpath, prepend classpath and process directory) in my main class, before creating my BodyTransformer. Now, it works.
I would like to ask whether there is a more proper way to solve this problem.
loadClassAndSupport is nor sufficicient. Here is what you should do. In your analysis' main method, before you call Soot's main method add the following:
Scene.v().addBasicClass("MyCounter");
Then within your analysis simply use Scene.v().getSootClass("MyCounter").
Related
This material says on page 10 that it is possible to run a JavaFX app without writing main. I suppose there is some predefined main inside jfxrt.jar which looks for a class extending Application and runs it.
Is that so? How to do that?
I suppose there is some predefined main inside jfxrt.jar which looks for a class extending Application and runs it.
This isn't really what's meant by that comment, and isn't how it works. All it is saying is that the "main class" doesn't need to define a main(String[] args) method if it is a subclass of javafx.application.Application. From the Oracle tools documentation for java:
The java command can be used to launch a JavaFX application by loading a class that either has a main() method or that extends the javafx.application.Application. In the latter case, the launcher constructs an instance of the Application class, calls its init() method, and then calls the start(javafx.stage.Stage) method.
(My emphasis)
So if the class specified on the command line is a subclass of Application, this behavior is simply baked into the JVM executable. Note that you still have to specify the class that is to be run; it just doesn't need a main method if it is an Application subclass. (The JVM is not scanning the classpath for candidate classes to run, as you seem to be describing in the question.)
The class to be run can be specified on the command line (java com.mycompany.MyApp) or can be specified in a jar file manifest in the usual way.
This was added in JDK 8, iirc.
Say an Android app uses a jar library and everything is working fine when the library is specified as a dependency:
dependencies {
...
...
compile 'org.example:example:1.1.1'
...
}
BUT : one of the classes in the org.example code needs to be tweaked.
One approach is to obtain the source code and put all of that in the java folder, and remove the module. When the tweak is made, that, and the entire library will be compiled.
Another approach is to make the tweak, compile, and replace the .class file within the .jar file.
Both of those methods have their drawbacks.
My question is: Is there an easier way to tweak code in a library?
When I tried just creating the package, placing the class that needed changing into the java folder, I got an error:
Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lorg/example/ClassNeedingChange;
I just wondered if there was a trick to getting code in the Java folder to override whats in a library jar file.
Additional Info:
Although not stated specifically above, the class that needs tweaking is buried in the library and is referenced by the library's code; I don't call it directly. For the simple case where the class that needed tweaking is one that my code (and only my code) called directly, then it would be a simple matter of extending the class using the Java construct. But for this simple case, I would not need to post this question.
Extend the class that needs tweaked in your code, and override the appropriate method.
Class A extends TweakMe {
#Override
public void someTweakedMethod() {
//Do stuff
}
}
A Java class made for video coding loads a DLL including C++ code
Unpacking debugging symbols for VideoSource.dll to \path
Checking for VideoSource.pdb...
Checking for videosource.pdb...
and then tries to instantiate a native (C++) class from that DLL:
// VideoSource() is implemented in C++ and wrapped with JNI,
// wrapper files were generated with SWIG
_videoProvider = new generated.VideoSource();
That works when the Java class is executed as a JUnit test (video data is extracted).
Same thing does not work when I launch the Java class as an OSGi service.
Essentially, the same code is executed. The DLL is still loaded successfully but the instantiation of the native (C++) class shown above now throws an exception:
java.lang.UnsatisfiedLinkError: generated.VideoSourceSWIGJNI.new_VideoSource()J
What is different when I launch the Java class as an OSGi service instead of executing it as a JUnit test? What can I do to make it work?
BACKGROUND
generated.VideoSource() is
public VideoSource() {
this(VideoSourceSWIGJNI.new_VideoSource(), true);
}
VideoSourceSWIGJNI.new_VideoSource() is
public final static native long new_VideoSource();
C++ implementation is
VideoSource::VideoSource() {
// init frame count
m_frame_cnt = 0;
[..]
}
Thanks, Puce, for pushing me a bit. After asking "would I have to try anything at all"? I got the answer relative quickly:
In order to resume sources (1, 2, 3, 4) with my own words:
When native code, e.g. .so or .dll libraries, shall be used in an OSGi bundle, corresponding libraries have to be declared in the bundle's manifest.
The manifest file may either be edited explicitely, as stated in mentioned sources, or implicitely via an appropriate plugin, e.g. apache felix, when using maven. Used plugin is configured in the POM file and will modify the manifest automatically.
I am using ASM with java agents. I have the following problem.
Whenever I see a "PUTFIELD" instruction within a method call, I want call a method from my agent library.
if (opcode == PUTFIELD) {
super.visitMethodInsn(Opcodes.INVOKESTATIC, "instrumenter/Util", "debug", "()V");
Util is a class defined by me with a static debug method. It stays in my agent.jar
java -javagent:agent.jar -jar test.Test works as I expected.
However, when I test this agent with some other jar files I got following error.
Exception in thread "main" java.lang.NoClassDefFoundError: instrumenter/Util
I suspect this occurs due to concurrency. Since the programs which create this error are mostly multi-threaded.
you could try to use -bootclasspath/p instead of -jar, probably, something is loaded too early for your util-class or some classloader-issue (e.g. a different (custom) classloader which cannot access your jar). if you put your jar into the bootclasspath, at least this source of defect is eliminated
I'd would like to examine a private method of an Android Activity by executing it within the Activity's public static void main(String[] args) method which I created.
I use Eclipse ADT and my naive approach of running the Activity as a Java application resulted in:
A fatal error has been detected by the Java Runtime Environment:
Internal Error (classFileParser.cpp:3174), pid=2936, tid=2980
Error: ShouldNotReachHere()
So I looked at the Run Configuration and found out that Android 3.1 is the sole entry in the Bootstrap Entries section of Classpath. I managed to configure the Build Path of the project so that the JRE is in the Bootstrap Entries too. Then I removed the Android 3.1 entry and added android.jar to User Entries.
The result of executing the Run Configuration is a RuntimeException:
Exception in thread "main" java.lang.RuntimeException: Stub!
at android.content.Context.(Context.java:4)
An alternative of executing some tests would be to fire up a JUnit test. But in the case of a private method this is cumbersome.
Is there a way to successfully run the main method of an Android Activity class?
There is another option for the problem at hand, if the private method - which should be examined through the execution of a main method - can be extracted to another class. This of course means that the method suddenly became at least protected.
But if the method is definded within a class that does not derive from android.app.Activity a main method can be defined. You only have to adjust the Run Configuration in Eclipse.
Run the class with Run as Java Application. This generates a new Run Configuration named like the class
Edit the newly creaded Run Configuration
Delete the Android library from Bootstrap Entries in the Classpath tab
Add JRE 6 or so to the build path of the project
Add this JRE to the Bootstrap Entries in the Classpath tab
Add android.jar, which resides in the platforms directory of the Android SDK in User Entries in the Classpath tab
Activity is very important from Android's point of view, Activity's lifecycle are collections of few methods which are handled by OS through out the activities' life.
public void onCreate(Bundle savedBunldeInstance)
is called as soon as the App is launched creating the activity. This is the entry point of an application in android. You must have the emulator or physical device for running Android app, Here the file is compiled 2 times, once by java compiler then by dalvik compiler.
DVM (Dalvik Virtual Machine) is located on the Android device (EMULATOR OR PHYSICAL), this is the reason why we need emulator or physical device to run it..and onCreate is the entry point for it.
On your request I am editing this post with an additional piece of information. The lines below are abstracted from http://developer.android.com/
Android applications don't have a single entry point.
(there's no main() function, for example).
for further details click this :
http://developer.android.com/guide/topics/fundamentals.html
The main method isn't the entry point in Android like in Java. You wanna override the
public void onCreate(Bundle savedBunldeInstance) method.