I am using Java reflection to invoke a method in a remote server from a local application. As part of the request to invoke the method, I am also sending the state of the Class object, which contains the value of the variables that are modified by the method during runtime, such that when the method is invoked remotely and the application gets the result from the server, the variables which were modified can be updated in my local application.
Client
public MyClass {
double var1;
...
public long dotest(){
Method toExecute;
Class<?>[] paramTypes = null;
Object[] paramValues = null;
Long result = null;
try{
/*
* Method specifications are stored and sent in a Class called MyPack to the server
*/
toExecute = this.getClass().getDeclaredMethod("localdotest", paramTypes);
Vector results = getCloudController().execute(toExecute,paramValues,this,this.getClass());
if(results != null){
result = (Long)results.get(0);
copyState(results.get(1));
}else{
result = localdotest();
}
} catch (SecurityException se){
} catch (NoSuchMethodException ns){
} catch (Throwable th){
}
return result;
}
public void copyState(Object state){
MyClass
localstate = (MyClass) state;
this.var1 = localstate.var1;
}
Server
myPack = (Pack) ois.readObject();
functionName = myPack.getfunctionName();
paramTypes = myPack.getparamTypes();
paramValues = myPack.getparamValues();
state = myPack.getstate();
stateDType = myPack.getstateType();
try {
Class cls = Class.forName(stateDType.getName());
Method method = cls.getDeclaredMethod(functionName, paramTypes);
try{
Object result = method.invoke(state, paramValues);
ResultPack rp = new ResultPack(result, state);
oos.writeObject(rp);
oos.flush();
} catch (IllegalAccessException ex) {
returnnull(oos);
} catch (InvocationTargetException ex) {
returnnull(oos);
} catch(Exception ex){
ResultPack rp = new ResultPack(null, state);
oos.writeObject(rp);
oos.flush();
}
However, I have notice that the state of the Class sent is always the same when the method is invoked remotely. So, I am planning to cache the state of the class in the server. The goal is to avoid sending the same state every time the method is invoked.
So far, I don't see any problem to do so. I tried to find something related, and these links 1, 2 are the most closer topics I found, but still I cannot get off this "itch" from my mind. Could somebody please point me out if there is any potential drawback to adopt such strategy. Thanks in advance.
Related
I wrote a small piece of code which takes a parameter ObjectInputStream and observe the data on a socket. The problem raise once readObject() function returns "null" and since the function observeSocket(ObjectInputStream in) takes only Object the subscriber executes onError() function and terminates the program.
But what I need is to continue observing sockets for Objects and return only if an Object is observed over the socket and only when observer unsubscribes should the function terminates its functionality. How could I modify the code to achieve the required functionality.
public Observable<Object> observeSocket(ObjectInputStream in){
return Observable.create(subscriber -> {
while(!subscriber.isUnsubscribed()) {
subscriber.onNext(getData(in));
}
subscriber.onCompleted();
});
}
public Object getData(ObjectInputStream in){
Object streamData = null;
try{
streamData = in.readObject();
}
catch(IOException e){
//e.printStackTrace();
}
catch(ClassNotFoundException e){
e.printStackTrace();
}
return streamData;
}
Avoid using Observable.create(OnSubscribe) because making backpressure aware and contract-compliant Observables is tricky business. This is a good candidate for using Observable.create(SyncOnSubscribe):
ObjectInputStream ois = ...;
Observable<Object> objects =
Observable.create(
SyncOnSubscribe.createStateless(observer -> {
try {
Object value = ois.readObject();
// you decide how end of file is indicated
// a common strategy is to write a null object
// to the end of the Object stream.
if (value == END_OF_FILE) {
observer.onCompleted();
} else {
observer.onNext(value);
}
} catch (Exception e) {
observer.onError(e);
}
}));
I'm trying to assign a value to a swing component through reflection. Let's use a JCheckBox for example. I have the following class:
public class JCheckBoxTest
{
private JCheckBox test;
public JCheckBoxTest()
{
this.test = new JCheckBox();
}
public reflectionTest()
{
Field field;
Method method;
field = this.getClass().getDeclaredField("test");
method = field.getType().getSuperclass().getDeclaredMethod("setSelected");
method.invoke(field, "true");
}
}
This code fails at:
method = field.getType().getSuperclass().getDeclaredMethod("setSelected");
because it cannot find the specified "setSelected" method since it is located inside the inner class "ToggleButtonModel" of the superclass "JToggleButton" which is extended by the "JCheckBox" class.
What would be the best approach to solve this?
Thanks.
Edit: Corrected typo in code.
Class#getMethod and Class#getDeclaredMethod both provide the means to supply the name of the method and optional parameters
JCheckBox#setSelected requires a boolean paramater, so you really should be using
method = field.getClass().getDeclaredMethod("setSelected", boolean.class);
But as you've noted, this is unlikely to work, instead, you could try
method = field.getClass().getMethod("setSelected", boolean.class);
Now, I've also had this fail to work as well, which is why I tend to use something like...
public static Method findMethod(Class parent, String name, Class... parameters) throws NoSuchMethodException {
Method method = null;
try {
method = parent.getDeclaredMethod(name, parameters);
} catch (NoSuchMethodException exp) {
try {
method = parent.getMethod(name, parameters);
} catch (NoSuchMethodException nsm) {
if (parent.getSuperclass() != null) {
method = findMethod(parent.getSuperclass(), name, parameters);
} else {
throw new NoSuchMethodException("Could not find " + name);
}
}
}
return method;
}
which is a little brute force.
So with that in mind...
JCheckBox cb = new JCheckBox();
try {
Method method = cb.getClass().getDeclaredMethod("setSelected", boolean.class);
System.out.println("1. " + method);
} catch (NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
}
try {
Method method = cb.getClass().getMethod("setSelected", boolean.class);
System.out.println("2. " + method);
} catch (NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
}
try {
Method method = findMethod(cb.getClass(), "setSelected", boolean.class);
System.out.println("3. " + method);
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
Which outputs something like...
java.lang.NoSuchMethodException: javax.swing.JCheckBox.setSelected(boolean)
2. public void javax.swing.AbstractButton.setSelected(boolean)
3. public void javax.swing.AbstractButton.setSelected(boolean)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at test.Test.main(Test.java:13)
Disclaimer
Reflection like this should be a last resort. It's slow and prone to code refactoring
I'm trying to build a client-server IDE, and I'm having problems with getting the error log/exception log of runtime exceptions from the in-memory compiled/run class.
My code looks like this:
public class ServerThread implements Runnable {
private ObjectInputStream objectInputStream;
private ObjectOutputStream objectOutputStream;
private ByteArrayOutputStream byteArrayOutputStream;
private PrintStream out;
public ServerThread(Socket socket) {
try {
objectInputStream = new ObjectInputStream(socket.getInputStream());
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
byteArrayOutputStream = new ByteArrayOutputStream();
out = new PrintStream(byteArrayOutputStream);
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
try {
StringBuffer sourceCode = new StringBuffer();
sourceCode.append(objectInputStream.readObject());
Class<?> myClass = MyJavaCompiler.compile("Test", sourceCode.toString());
Method mainMethod = myClass != null ? myClass.getDeclaredMethod("main", String[].class) : null;
Object myObject = myClass.getConstructor().newInstance();
try {
System.setOut(out);
System.out.print(mainMethod.invoke(myObject, new Object[]{null}));
objectOutputStream.writeObject(byteArrayOutputStream.toString());
} catch (InvocationTargetException e) {
Class<?>[] exceptionsList = mainMethod.getExceptionTypes();
for(Class<?> c : exceptionsList){
objectOutputStream.writeObject(c.getName());
}
}
} catch (Exception e) {}
}
}
and this is the compiler:
import javax.tools.*;
import java.util.Arrays;
/**
* Created by alin on 8/23/15.
*/
public class MyJavaCompiler {
private static JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
public static Class<?> compile(String className, String sourceCodeInText) throws Exception {
JavaSourceFromString sourceCode = new JavaSourceFromString(className, sourceCodeInText);
CompiledCode compiledCode = new CompiledCode(className);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceCode);
DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(ClassLoader.getSystemClassLoader());
MyJavaFileManager fileManager = new MyJavaFileManager(javac.getStandardFileManager(null, null, null), compiledCode, dynamicClassLoader);
JavaCompiler.CompilationTask task = javac.getTask(null, fileManager, null, null, null, compilationUnits);
boolean result = task.call();
if(result){
System.out.println("SUCCESS");
return dynamicClassLoader.loadClass(className);
}
else{
System.out.println("FAIL");
return null;
}
}
}
At this moment, when I have, for example NullPointerException in my in-memory class, I get "[]" sent to client.
EDIT:
Thanks Holger for your answer and feedback. I managed to get the code to do what i wanted by simply adding e.printStackTrace(PrintStream), code below:
try {
System.setOut(out);
System.out.print(mainMethod.invoke(myObject, new Object[]{null}));
objectOutputStream.writeObject(byteArrayOutputStream.toString());
} catch (InvocationTargetException e) {
e.printStackTrace(out);
objectOutputStream.writeObject(byteArrayOutputStream.toString());
}
The idea was to redirect my error output from my in-memory class to client from server.
You should get used to a consistent behavior regarding null treatment. Here
Class<?> myClass = MyJavaCompiler.compile("Test", sourceCode.toString());
Method mainMethod = myClass != null ? myClass.getDeclaredMethod("main", String[].class) : null;
Object myObject = myClass.getConstructor().newInstance();
You are considering that myClass could be null when initializing mainMethod but right in the next line you are unconditionally invoking getConstructor() on myClass which would lead to a NullPointerException when myClass is null. Even when that didn’t fail, you have assigned null to mainMethod in case myClass is null, but are going to call invoke, again without checking for null.
Nevertheless, when your compile method returns a non-null value, you will proceed, but in the case you receive an InvocationTargetException, you are not going to send anything related to that exception, in fact you are not accessing e at all, but instead you are sending the result of mainMethod.getExceptionTypes() which are the types which that method declares via throws clause. That list might indeed be empty, the main method doesn’t need to declare any exceptions and may still throw RuntimeExceptions or Errors.
You are also performing myClass.getConstructor().newInstance(); outside that try … catch clause and any throwable thrown by this constructor will get handled by the outer try … catch in the worst way ever possible, catch (Exception e) {} …
I have the following code structure.
A transaction handler of type Transaction which is a field in a Client Handler class, which talks to a Server. (the client handler and the server are collocated), the client talks to the client handler via serialized object messages.
When a new transaction request comes in from the client, (comes on thread using the readObject() method of an object input stream), I then do a series of trx_handler.setFoo(trx.getFoo))). This works fine, I can handle the first request. But when a subsequent request comes in (which only starts getting executed after the first request finished due to the loop structure, I find that the trx handler has been reinitialised to its default values, the object is still there, but all the values inside are the defaut ones. What can cause this problem?
My first guess would be garbage collection, but in my Client Handler class, there is always a pointer to this trx_handler.
The code below illustrates what happens. A statement would first be of type start, so the trx_handler will be correctly initialised. handle_statement will then be called. Subsequent statements should then be received, but at this point the trx_handler has been reinitialised to its default settings, so the access_set field is null, the session id as well, and none of the modification made to the object in hande_statement are visible
Thanks
public class Handler {
private Statement trx_handler;
/* Constructor initialises trx_handler to new Statement(); */
public ClientHandler(final Socket socket, long uid, Server server, ObjectInputStream ois) throws IOException, Exception {
LOGGER.info("Constructing Handler");
this.uid = uid;
this.server = server;
this.socket = socket;
this.database = server.getDB();
this.trx_sys = database.getTransactionManager();
create_listening(socket, ois);
out = socket.getOutputStream();
oos = new ObjectOutputStream(out);
this.trx_handler = new Statement(false);
}
private void create_incoming(final Socket socket, final ObjectInputStream stream) {
Thread incoming = new Thread() {
#Override
public void run() {
ObjectInputStream ois = stream;
InputStream in = null;
while (true) {
Object statement = null;
try {
statement = ois.readObject();
execute_stat(statement, socket, null);
LOGGER.info("Ready to execute next ");
} catch (SocketException e) {
LOGGER.severe("Connection Closed");
return;
} catch (IOException e) {
LOGGER.severe("Connection Closed");
return;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
String error_message = e.getMessage();
send_error(socket, error_message);
}
}
}
};
incoming.setDaemon(true);
incoming.start();
}
private synchronized void execute_stat(Statement trx) {
if (trx.getTransactionState() == Consts.trx_end) {
trx_sys.commitTransaction(trx_handler);
return;
} else if (trx.getTransactionState() == Consts.trx_start) {
try {
trx_handler.setAccessSet(trx.getAccessSet());
trx_handler.setSession_id(trx.getSession_id());
trx_sys.startTransaction(trx_handler);
handle_statement(socket, trx_handler);
/* TEST HERE THAT FIELDS IN TRX_HANDLER ARE CORRECTLY SET (INCLUDING SOME MODIFIED IN
handle_statement and they are correctly set */
return;
} catch (Exception ex) {
Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
LOGGER.info("Execute Trx: stat");
/* Can't see modifications made in the start case */
Statement stats = trx.getStatement();
trx_handler.setStatement(stats);
handle_statement(stats, socket, trx_handler);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
You need to either send a brand new object for each transaction, use ObjectOutputStream.writeUnshared(), or else call ObjectOutputStream.reset() between sends.
I have seen this method in android source code.
protected LocaleConfiguration doInBackground(Void... unused) {
LocaleConfiguration localeConfiguration = new LocaleConfiguration();
readConfiguration(Launcher.this, localeConfiguration);
return localeConfiguration;
}
private static void readConfiguration(Context context, LocaleConfiguration configuration) {
DataInputStream in = null;
try {
in = new DataInputStream(context.openFileInput(PREFERENCES));
configuration.locale = in.readUTF();
configuration.mcc = in.readInt();
configuration.mnc = in.readInt();
} catch (FileNotFoundException e) {
// Ignore
} catch (IOException e) {
// Ignore
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// Ignore
}
}
}
}
why not something like this
private static LocaleConfiguration readConfiguration(Context context) {
LocaleConfiguration configuration = new LocaleConfiguration();
DataInputStream in = null;
try {
in = new DataInputStream(context.openFileInput(PREFERENCES));
configuration.locale = in.readUTF();
configuration.mcc = in.readInt();
configuration.mnc = in.readInt();
} catch (FileNotFoundException e) {
// Ignore
} catch (IOException e) {
// Ignore
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// Ignore
}
}
}
return configuration;
}
what is the advantage of modifying argument instead of returning new value
The advantage of modifying an argument instead of returning a new instance is that you put control of instantiation in the hands of the calling code - i.e. you allow it to re-use an existing instance.
The 'modifying argument' approach allows you to initialise an object using several such methods. e.g.
LocaleConfiguration localeConfiguration = new LocaleConfiguration();
readConfiguration(Launcher.this, localeConfiguration);
readSomeOtherConfiguration(Launcher.this, localeConfiguration);
return localeConfiguration;
Arguably you could do the same thing by returning the same instance as was passed in as a parameter, but I personally think that's asking for trouble.
Another possible reason might be if the cost of instantiation was high, you might want to recycle an old object. This doesn't appear to be the case with the code you present though, and it's an optimisation so only think about doing this if absolutely necessary!
Personally I would tend to take the 'return a new instance' approach unless there's a specific reason not to. I think it's simpler and decreases the likelihood of subtle errors in the calling code.