reflection – Getting an Object by reference in Java

The Question :

1 people think this question is useful

New to this website, and excited to share my first question 🙂

Ok so I’m going to be explaining what I have set-up currently so that my question can be understood better.

I have 2 java applications:

  1. Logic Application (Where all the heavy load occurs)
  2. Instrumented Application (Application instrumented into a running game)

What I do with these 2 applications is extract information from a game using the Instrumented Application then send it to the Logic Application.
The extraction of information/data is done through the Java Reflection API. Then after the information has been extracted, it is sent to the Logic Application through RMI (more on this below).

The reason I have 2 applications instead of 1 is because the game runs on Java 7 (old game), so the Instrumented Application runs on Java 7, and I can run the Logic application on whatever java version I want.

The way I transfer data/information between the 2 is through RMI (Remote Method Invocation).
Explanation: The Logic application invokes a getter method at the Instrumented App, and the method uses the Reflection API to grab the field value from the game it’s instrumented into and return it.

Now as you guys have understood what I’m basically doing, now comes the challenge that I have been bamboozled by for quite some time.

Problem:

Most of the Field Values that are returned by Reflection are Serializable, therefore they pass-through RMI with no problem. But, some are Un-serializable objects like for an example “Item”.
“Item” is an object and it holds 3 values: ID, Name, Quantity. So my thought was to make a wrapper and send the wrapper and it would be problem solved right? but no, another challenge popped up.

The challenge that popped up was: What if I needed to know the quantity of the object “Item” that I pulled out at another time? If my whole thing was 1 application, I would’ve used the Reflection API to get the Field using the Object by:
getClassLoader().loadClass("ItemClass").getDeclaredField("Item").get(ObjectThatIPreviouslyFetched);
But since I have to transfer the objects over to the Logic Application, I cannot transfer the Object itself “Item” so I have no way to return to that object and get updated information unless I look for the object again which is a waste of resources and makes my whole process slower.

Applications work like so:

Instrumented App -> Reflection -> Game -> Field Value (Object called Item) -> Wrapper -> RMI -> Logic Application (Object information is sent but Object itself can’t be sent due to it being unserializable)

Summary of the question (using the pointers just above): How can I get the Object (Item) back so I can get updated information about it using Reflection.

This is the method I made to get the Field Values (Objects):

   /**
    *
    * @param params owner;fieldName;multiplier
    * @param object null if static
    * @return returns the value of the object provided.
    */
   public Object getFieldValue(String params, Object object) {
       String[] paramsSplit = params.split(";");
       try {
           Class<?> clazz = classLoader.loadClass(paramsSplit[0]);
           Field field = clazz.getDeclaredField(paramsSplit[1]);
           field.setAccessible(true);
           Object o = field.get(object);
           if(!paramsSplit[2].equals("0")) return getMultipliedValue((Number) o,paramsSplit[2]);
           else return o;
       } catch (IllegalAccessException | NoSuchFieldError | ClassNotFoundException | NoSuchFieldException e) {
           e.printStackTrace();
       }
       return null;
   } 

This method is found in the Logic Application and it attaches the Instrumented Application to the running game:

    public void inject() {
        VirtualMachine vm = null;
        try {
            vm = VirtualMachine.attach(String.valueOf(pid));
            vm.loadAgent(Info.baseLocation());
        } catch (AttachNotSupportedException | IOException |
                AgentLoadException | AgentInitializationException e) {
            e.printStackTrace();
        } finally {
            try {
                if(vm != null) vm.detach();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

I hope everything was understandable, I’m not an English native so I apologize if something seems wrong.

Thank you!

The Question Comments :
  • Could your instrumented application maintain a data structure which contains the Items, indexed by some key. The key could be added to the Item data returned to your logic application, so that it can ask the instrumented application for updated information about the item associated with the key.
  • @tgdavies I have thought of this, creating a HashMap and adding the objects with unique Ids and then sending the unique ids with the wrapper to the logic application. But the problem here is .. what if the object was an array of unserializable objects.. then I’d have to add all the elements into the hash map.. and also after a while the hash map will be huge
  • I think you would have exactly the same problem if you had only one application: you need to be able to look up objects you’ve previously retrieved.
  • @tgdavies No I wouldn’t because I could just use reflection and get the object information using it. So like suppose I looked through an array and found the object I wanted say… an item with the name “Fire Arrows” and it has a quantity of “10”. then I can just wrap it in a wrapper and use the same object at a later date and get updated information about it using reflection by doing getClassLoader().loadClass(“ItemClass”).getDeclaredField(“Item”).get(Object_That_I_Retrieved_Previously);
  • But how are you going to find the object again at a later date? You’ll need to have reference to it in some data structure.

Add a Comment