Android - dynamically load class into memory - java

DexClassLoader is great but works only by loading the compiled class as dex/jar file from the internal/external storage.
How can I load class directly into memory, without writing anything to the card first?
I am aware of the Java-Runtime-Compiler (compiles String to Class on-the-fly) from Peter Lawrey, which would be perfect, but it does not work in android.

The general principles for writing Java class loaders apply here as well, so basically what you need to do is write a class loader that can produce a Class instance, for example by invoking defineClass(). Of course this involves creating a valid array of dex bytecode. I have not done so yet, and besides very special occasions I would refraim from attempting to do so anyway. If you follow this road, remember to only use classloader features that have been present in Java 5 and 6.

As Thomas stated, you can reflectively invoke the protected defineClass() method of the ClassLoader into which you would like to load your class.
Here's an example of how this could be achieved:
public static Class<?> loadClass(byte[] code, ClassLoader loadInto) throws InvocationTargetException
{
try {
Method m = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
m.setAccessible(true); // Make sure we can invoke the method
return (Class<?>) m.invoke(loadInto, code, 0, code.length);
}
// An exception should only be thrown if the bytecode is invalid
// or a class with the same name is already loaded
catch (NoSuchMethodException e) { throw new RuntimeException(e); }
catch (IllegalAccessException e){ throw new RuntimeException(e); }
}
Although, what I'm getting the feeling that you're referring to is runtime compilation of a String containing valid Java into bytecode, based on the link you included. Though I do not know of any way of doing this, I would recommend you take a look at this: https://github.com/linkedin/dexmaker

You can do it by InMemoryDexClassLoader

Related

The exception "NoSuchMethodError" appears in a multi module project of maven [duplicate]

On my current project, I've felt the need to create a sort of simulated callback system in Java using reflection. However, I'm having issues getting my reflection to actually function. The code at fault follows:
public Callback(Object parentObj, String methodName, Class<?>...parameters)
{
if(parentObj == null)
throw new IllegalArgumentException("parentObj cannot be null", new NullPointerException());
Class<?> clazz = parentObj.getClass();
// Trace debugging, see output
for(Method m : clazz.getDeclaredMethods())
if(m.getName().equals("myMethod")) System.out.println (m);
try { this.method = clazz.getMethod(methodName, parameters); }
catch(NoSuchMethodException nsme) { nsme.printStackTrace(); } // Exception caught
catch(SecurityException se) { se.printStackTrace(); }
this.parentObj = parentObj;
this.parameters = parameters;
}
When I construct the Callback object, I'm using syntax like this:
new Callback(this, "myMethod", boolean.class)
When I try to create my pseudo-callback, it hits the NoSuchMethodException catch block. I've included some trace debugging above to show the output of one of my methods failing. The output:
private void my.package.MyClass.myMethod(boolean)
java.lang.NoSuchMethodException: my.package.MyClass.myMethod(boolean)
at java.lang.Class.getMethod(Class.java:1605)
at my.package.other.Callback.<init>(Callback.java:63)
I couldn't figure the problem out, so I started hunting, to little avail. The best I could find was mention of versioning conflict between the compiled JAR and the runtime. However, MyJar.jar/META-INF/MANIFEST.MF contains Created-By: 1.6.0_02 (Sun Microsystems Inc.). My IDE is running C:\Program Files\Java\jdk1.6.0_02\bin\javac.exe to compile my project. I'm using C:\Program Files\Java\jdk1.6.0_02\bin\java.exe to run my JAR.
I'm at a loss why Class.getMethod is claiming the method doesn't exist, but Class.getMethods seems to have no problem finding it. Help? :(
Your method is private but getMethod() only returns public method.
You need to use getDeclaredMethod().
You need the parameter list to be absolutely correct for the method you want for the call to succeed.
I've found that tiny steps are important when doing reflection because the compiler doesn't help. Write a small snippet which actually invokes exactly the method you want to in this particular case, and then when that works, generalize it into the framework here. I would focus on the parameters passed.
The Javadoc for getMethod isn't explicit, but it looks like it might throw a NoSuchMethodException for methods that aren't public, and your method is private.
The versioning issue that can cause NoSuchMethodException isn't a difference between the compiler versions. It's a difference in the version of (in your case) MyClass at compile time versus runtime.
Since you're using reflection you issue might have nothing to do with versioning, though. Certainly that would not explain different behavior between getMethod and getDeclaredMethods, because you're running them against the same Class instance, hence a version difference isn't really possible.
Are you sure that the parameters match your actual method?

NMS: "The object is not an instance of the declared class" error

so I was trying to use Reflection once again to make version dependent classes (Net Mincraft Server aka NMS) work with all versions of the game. I've run into a problem with a method and I can't figure what the error is.
public NPCReflection(UUID id, String name, World world) {
this.id = id;
this.name = name;
this.entityId = (int) Math.ceil(Math.random() * 1000) + 2000;
try {
Class<?> nmsServerClass = utils.getNMSClass("MinecraftServer");
Class<?> nmsWorldServerClass = utils.getNMSClass("WorldServer");
Class<?> obcCraftServerClass = utils.getOBCClass("CraftServer");
Class<?> obcCraftWorldClass = utils.getOBCClass("CraftWorld");
Class<?> nmsEntityPlayerClass = utils.getNMSClass("EntityPlayer");
Class<?> nmsPlayerInteractManager = utils.getNMSClass("PlayerInteractManager");
Class<?> obcServerClassInstance = obcCraftServerClass.cast(Bukkit.getServer()).getClass();
Object nmsServerInstance = obcServerClassInstance.getMethod("getServer").invoke(obcServerClassInstance);
Class<?> obcWorldClassInstance = obcCraftWorldClass.cast(world).getClass();
Object nmsWorldInstance = obcWorldClassInstance.getMethod("getHandle").invoke(obcWorldClassInstance);
Constructor<?> entityPlayerConstructor = nmsEntityPlayerClass.getConstructor(nmsServerClass, nmsWorldServerClass, GameProfile.class, nmsPlayerInteractManager);
Object entityPlayer = entityPlayerConstructor.newInstance(nmsServerInstance, nmsWorldInstance, new GameProfile(id, name), nmsPlayerInteractManager.getConstructor(nmsWorldServerClass).newInstance(nmsWorldInstance));
utils.setValue(entityPlayer, "a", entityId);
this.entityPlayer = entityPlayer;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
This is the part that is giving me errors.
More precisely this 2 lines.
Class<?> obcServerClassInstance = obcCraftServerClass.cast(Bukkit.getServer()).getClass();
Object nmsServerInstance = obcServerClassInstance.getMethod("getServer").invoke(obcServerClassInstance);
And the error is saying that "The object is not an instance of the declared class" if I remember correctly (not at the pc ATM).
But bukkit.getServer returns the Server object correctly and I don't know why it does that.
This is the reference without reflection.
Bukkit.getServer().getPluginManager().registerEvents(this, this);
MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer()).getServer();
WorldServer nmsWorld = ((CraftWorld) Bukkit.getWorlds().get(0)).getHandle();
npc = new EntityPlayer(nmsServer, nmsWorld, new GameProfile(UUID.fromString("c793afb5-c4b7-4fdb-a100-b761315913c4"), "PogoStick29"), new PlayerInteractManager(nmsWorld));
Standard warning first: Don't use reflection like this. Especially don't use straight-up strings to drive it. Use enums to deliver the strings that your getXxxClass methods use.
That said, you are trying with
Class<?> obcServerClassInstance = obcCraftServerClass.cast(Bukkit.getServer()).getClass();
first to cast whatever getServer() returns to a type represented by obcCraftServerClass. That type must be in the class hierarchy of the type returned by getServer. Why do you need that particular class? If you did this right, the class represented by obcCraftServerClass will be a supertype of that returned by getServer(), and you can just use that type without all that messy casting. If the class represented by obcCraftServerClass is not a supertype of that returned by getServer(), you screwed up.
Do all of this without all that reflection. Really. You shouldn't have to do more reflection than instantiate objects via the types returned by the utils.getXxxClasscalls, and just assign the resulting instance references to variables of their supertypes. Stop screwing around with all that Class<?> garbage.
Your stumbling around with reflection will only lead to unmaintainable tangles, heartache, and broken code. Use object-oriented programming (or better, type-oriented), and you will be much happier.
I see why you need to cast the class because, well, I'm also using the API. However, you're wrong when you say this is the only clean way. Reflection has many disadvantages: it looks messy, it's hard to follow and it slows down your code (especially when implemented like that). Also, if you're planing to use reflections for accessing NMS fields and methods it's verry likely it will get screwed up in a future version, as Mojang reobfuscates them each revision. I recommend creating an interface and several implementations for it depending on version. This way, you will still have to update your plugin every new revision (only three per major version. For instance, you can only have 1_9_R1, 1_9_R2 and 1_9_R3) but you could simply copy/paste your old code used in some older version and re-import the classes to match the current version, and, if needed, change the fields and methods accessed accordingly (you would still have to do that with reflection).
To make your plugin work on multiple versions at the same time, you should take a look into the maven module system. You can create several independent modules: Base plugin, interface and implementation(s). Whenever a new version pops up, you just add a new implementation module. To check which module you need to use, you get the server version on startup and match it to the right implementation. Mbaxter on the bukkit forums made a really nice tutorial about this: https://bukkit.org/threads/support-multiple-minecraft-versions-with-abstraction-maven.115810/. Hope this helps!

Should I create a custom exception type so my code is easier to unit test

In my unit test, I test a method for an expected RuntimeException and I want to distinct those thrown by my component from ones thrown by the code called in the method.
Creating a custom exception type is unnecessary and does not solve the problem if the method throws the same exception type but for different reasons, e.g. InvalidArgumentException.
Looks like the only way to tell them is the message or the error code. Because the message can be changed during development, the error code seems the only reliable option.
What is the best practice for creating of system of error codes so they don't conflict with ones of external packages, eg. third party libraries?
Creating a custom exception type is unnecessary and does not solve the
problem if the method throws the same exception type but for different
reasons, e.g. InvalidArgumentException.
Why do you think it's unnecessary? This is what you should do. Derive your own custom exception classes, throw their instances from your code and catch them outside (in your unit tests). The catch statement can be repeated in anticipation of multiple different exception classes:
try {
// something
} catch (MySpecificException e) {
// you know that your code threw this
} catch (Exception e) {
// this is coming from somewhere else
}
--Edit--
Sorry, I didn't see the java tag. Even though the following example uses PHP constructs, the principles should still apply.
--Original--
I use custom exception codes in only a few, very specific cases, and I store these codes in a custom exception class which extends the default exception class. They are stored in the class as constants, as the value doesn't really matter, but the context does.
Consider:
class CoreLib_Api_Exception extends Exception
{
const EXCEPTION_FORMAT = '%s (%s): %s';
const CODE_FILE_DNE = 100;
const CODE_DIR_BASE_EQUALS_REMOVE = 101;
const CODE_XML_READER_UNABLE_TO_OPEN = 200;
const CODE_XML_READER_UNABLE_TO_READ = 201;
}
// Example usage
class CoreLib_Api_Reader
{
protected function getReader()
{
$reader = new CoreLib_Api_Xml_Reader();
if (!#$reader->open($this->getFileUri())) {
$e = new CoreLib_Api_Exception(sprintf('Could not open %s for parsing', $this->getFileUri()), CoreLib_Api_Exception::CODE_XML_READER_UNABLE_TO_OPEN);
throw $e;
}
}
}
// Calling code
try {
$reader = CoreLib_Api_Reader();
$reader->setFileUri($fileUri);
$reader->getReader();
} catch (Exception $e) {
// If code is anything other than open, throw it
if ($e->getCode() !== CoreLib_Api_Exception::CODE_XML_READER_UNABLE_TO_OPEN) {
throw $e;
}
$e = null;
$reader = null;
}
By using the exception code, I can check to determine if the reader is unable to open the file, if so ignore the exception and move on, otherwise throw the exception and break the flow.
And if one of my exception codes collides with a third party exception code, it doesn't matter, as I mentioned before, using constants, the context will dictate which code I want to match on.
I test a method for an expected RuntimeException
I think this is a mistake. A RuntimeException should be used only for indicating bugs in the code that the code itself can detect. Testing should test only for specified (defined) behaviour. But when there is a bug in some code, its behaviour is undefined (who knows where the bug could be or what it might do). So there is no point in trying to specify what RuntimeExceptions some code should throw; that is like specifying how the code should behave "in the presence of a bug". Throwing particular RuntimeExceptions with particular messages should be seen as a courtesy to the maintenance programmer (who is likely to be you).

Why is call to static method in Java not being made?

I have a fairly standard creational pattern whereby a class exposes a static method for returning instances of itself, like so:
public class MyClass {
private MyClass(/*parameter list*/) {
// internal construction
}
public static MyClass GetMyClass(/*parameter list*/) {
return new MyClass(/*parameter list*/);
}
}
...
//this line wont break in the debugger and seemingly never gets called - why?
MyClass inst = MyClass.GetMyClass(/*parameter list*/);
However, inst is always null. I can't break on the line that calls the static method, the debugger just ignores it - what's going on?
Edit: Thanks for the suggestions.
All projects have been cleaned and rebuilt (manully in NetBeans)
I have added a break in the static method and no it isn't hit.
Yes, the code above is being called (ultimately) in a constructor for a Swing 'FrameView' though it surely shouldn't matter where I am calling this from, should it?
There is no exception swallowing anywhere
Side note, other than the missing class declaration (which was a typo) why is this not valid Java? Why is this obviously C# code? Explanations would be more helpful than downvotes :)
Edit II: The Params is just supposed to indicate a whole load of parameters - sorry if this confused anyone, I obviously know parameters have type declarations and so on, the code above was intended as a quick shorthand version rather than a full and (complicated) real sample...
A couple of options:
An exception is being thrown which you're somehow missing
You're not debugging the code that you think you are (i.e. your built code is out of date with your source code)
The latter is the most likely one, IMO.
Apparently you're swallowing an exception inside the constructor something like:
try {
// Something.
} catch (Exception e) {
}
You should never do that. It makes debugging and nailing down the root cause much harder. Rather throw it or at least do a e.printStackTrace(). If throwing and you don't want to use the throws clause for some reasons, consider using a RuntimeException (or one of its subclasses). E.g.
try {
// Something.
} catch (Exception e) {
throw new RuntimeException("Construction failed.", e); // Try to be more specific, e.g. IllegalArgumentException or so. Or just write robust code, i.e. nullchecks and so on.
}
or (but in my opinion not very applicable in your case):
try {
// Something.
} catch (Exception e) {
e.printStackTrace();
}
I understand that you are trying to make a simple example to show your problem, however if you add the appropriate type statements into your sample code, then it both compiles and does what you expect.
However, in your original codebase you could simply place the breakpoint in the static method to see whether or not it is called.
Maybe a simple question, but you never know… are you sure that you are running the code that you think you are running? That is, is everything recompiled and built from the latest sources?
There is nothing wrong with :
MyClass inst = MyClass.GetMyClass(Params);
It depends what is before or after that line of code.
Start by doing this:
public class MyClass
{
private MyClass(/*parameter list*/)
{
System.out.println("entering MyClass(...)");
// internal construction
System.out.println("leaving MyClass(...)");
}
// Java uses lower case for method names - so get not Get
public static MyClass getMyClass(/*parameter list*/)
{
final MyClass foo;
System.out.println("entering getMyClass(...)");
foo = new MyClass(...);
System.out.println("leaving getMyClass(...)");
return (foo);
}
}
...
MyClass inst = MyClass.getMyClass(/*parameter list*/);
See if outside the debugger the code gets called.
If you are catching any exceptions, at the very least do:
catch(final WhateverException ex)
{
// at the very least do this so you can see that the exception happens
ex.printStackTrace();
}
Avoid catching Throwable, Error, Exception, and RuntimeException. Infact the best way do do it is get rid of all the catch statements and then only add catches for what the compiler tells you that you have to have.
The other thing is you do not say where MyClass inst = MyClass.getMyClass(/parameter list/); is called from. It is entirely possible that that line never gets hit.
You mention that you're calling this from the constructor of a FrameView, but I assume you're talking about an implementation or extension of that interface/object. My reasoning was to make sure you wern't recursively invoking the constructor.
I think the reason why catching java.lang.Exception isn't catching the problem is because it is likely too specific in this case. Try catching java.lang.Throwable which will catch errors like java.lang.NoClassDefFoundError - that frequently crops up when you have a jar missing somewhere.

How to link to a package but only optionally execute an action based on existence/availability of package at runtime?

From the perspective of a cross application/applet java accessibility service, how would you link to a package but only optionally execute an action based on existence/availability of a package (being already loaded) at runtime?
I think what I'm interested in here is a way to resolve the class identity crisis but rather than the issue being between 2 apps sharing objects, being a service loaded at a higher level of the class loaders.
It seems like reflection is the way to go, but I am not sure how or if I can implement a derived class this way. I need to add a specific listener derived from the specific optional classes, I can load the listener using the applet class loader but the internals still fail. Say you wanted to add an JInternalFrameListener, but Swing wasn't guaranteed to be available, using reflection you can find the method to add the listener, but how can you create and have the frame listener work if it cannot find any of the related classes because they can't be found in the base classloader! Do I need to create a thread and use setContextClassLoader to the classloader that knows about swing so that I can get the class to be loaded reliably? simply trying to set the class loader on my existing thread didn't seem to work.
Earlier description of issues
Sorry, I'm not quite sure what to ask or how to make this clear, so it rambles on a bit.
Say a class uses some feature of another, but the other class may not always be available - say finding the website from JNLP if this is a JNLP app.
At one stage I thought that simply compiling against JNLP would mean that my class would not load unless JNLP was available, and so to identify this optional section I simply wrapped a try{} catch( NoClassDefFoundError ) around it.
Later something changed (perhaps changing jdk or ?? I don't recall) and it seemed that I should also use a try{} catch( ClassNotFoundException ).
Now I wanted to extend this idea to other optional features, but it doesn't seem to work consistently.
Say I wanted to add some feature to do something more advanced in a JRE1.6 runtime using the same jar and classes as I run in a JRE1.3, or say I want to handle some controls in a specific gui toolkit which may not always be used like SWT or oracle.forms.
Is there some way of doing this more reliably? It just seems wrong to cause an exception and catch it to ignore it all the time.
The current issue comes down to being able to compile against oracle.forms but then the accessibility component installed in ext is unable to access the oracle.forms classes even though objects from the oracle.forms package have been created. If I throw the frmall.jar into the ext directory to test then the accessibility component works up to the point that the whole lot gets flakey because of the different versions of the same package.
I seem to be caught up on an issue with the class loader not being the right one or something (??). How do I find the right one?
Edit:
The answers so far are kindof interesting but not quite getting me where I want to be.
In the case of the gui components I currently compile in the form of a factory something like...
import oracle.forms.ui.*;
import java.awt.*;
static public IComponentNode newNode( INode parent, Component component ) {
System.out.println( component.getClass().toString() );
try{
if( component instanceof FormDesktopContainer )
... does stuff here like return new FormDesktopNode( parent, (FormDesktopContainer) component )
} catch ( NoClassDefFoundError a ) {
System.out.println( a.getMessage() );
}
where it prints out class oracle.forms.ui.FormDesktopContainer and then throws and exception on the instanceof call with NoClassDefFound thus printing out oracle/forms/ui/FormDesktopContainer
So how can it have an instance of a class yet not be able to find it?
How about this? messy, but it ought to work:
public boolean exists(String className){
try {
Class.forName(className);
return true;
}
catch (ClassNotFoundException){
return false;
}
}
You can check the availability of a class by calling
ClassLoader.getSystemClassLoader().loadClass("my.package.MyClass")
if it throws a ClassNotFoundException, it's not available. If you get the Class object, it is. You can then choose behaviour based on whether or not the class is available.
I suggest compiling the majority of your code against your minimum target. Have code that uses particular optional libraries clearly separated, but dependent upon the bulk of your code. Dynamically load the code that uses optional libraries once. The main class should do something that checks for the presence of the required library/version in its static initialiser.
In the case of JNLP, your JNLP main class load the JNLP dependent code statically.
(Note that attempting to catch class loading related exceptions from normally linked code is unreliable.)
getSystemClass loader was not useful for this purpose as there where multiple possible class loaders to interact with based on which applet the given window was in. The accessibility components being loaded at a more base class loader cannot see the applet specific classes.
To interact with the objects reflection does the job, though it does add so much more to maintain.
// statically linking would be
return component.getText();
// dynamically is
try {
return (String)component.getClass().getMethod("getText", new Class [] {}).invoke(component, new Object [] {});
} catch (Throwable e) {
e.printStackTrace();
}
The trickier bit is in writing a class derived from an interface that is not directly accessible, using the Proxy service allows this to be accomplished, providing the proxy service the applet specific class loader and the dynamically loaded class for the interface.
public void addListener(Container parent) {
if (parent == null) { return; }
if ("oracle.forms".equals(parent.getClass().getName())) {
// Using the class loader of the provided object in the applet
// get the "class" of the interface you want to implement
Class desktopListenerClass = Class.forName( "oracle.DesktopListener"
, true, parent.getClass().getClassLoader());
// Ask the proxy to create an instance of the class,
// providing your implementation through the InvocationHandler::invoke
Object desktopListener = Proxy.newProxyInstance(
parent.getClass().getClassLoader()
, new Class[] { desktopListenerClass }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("functionName".equals(method.getName())) {
// do stuff
}
return null;
}
});
// do something with your new object
Method addDesktopListener = parent.getClass().getMethod("");
addDesktopListener.invoke(parent, desktopListener);
}
}
examples cut down to show general method

Categories

Resources