问题
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:
- Logic Application (Where all the heavy load occurs)
- 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!
回答1:
There's is no "Right" answer for this question.
I went for making a map that stores the objects, and assigned a unique key for every object. I then sent the object's unique key over RMI, now I can just get the Object using the unique key and send over the object's inner information at any time.
回答2:
If the objects do not have circular references try JSON. GSON is recommended.
Another way would be to register them in memory using UnSafe then grabbing the objects using the address. Though you have to free it later on or else its scortched earth.
来源:https://stackoverflow.com/questions/65067030/getting-an-object-by-reference-in-java