I'm writing Android application that has Java and native part. Java part sends messages to native part and receives answers back. Native part does all work on separate thread and when it returns answer I want to handle answers on main thread. Here is part of my extended Application class:
#Override
public void OnMessage(final Message msg, final long answerTo) {
Log.i(TAG, msg.ToStr()); // OK
handler.post(new Runnable() {
#Override
public void run() {
Log.i(TAG, msg.ToStr()); // Fatal signal 11 (SIGSEGV)
// at 0x74616862 (code=1), thread 13255
}
});
}
Native code calls OnMessage method on it's thread and trying to pass it to UI thread through Handler. And when I try to use any method of msg inside UI thread my program fails with SEGSEGV.
Significant fact is that Message class is the wrapper for C++ Message class. Wrapper was generated by SWIG.
I tried to debug it in GDB, and GDB even shows me stack trace, which ends in native Message.toStr method. But gdb refuses to print variables, saying "No symbol "*" in current context".
Please, help me to resolve this issue.
I don't think you are using Handler properly for what you are trying to do (copy object across threads). Check out the blog post here:
http://techtej.blogspot.com/2011/02/android-passing-data-between-main.html
Specifically the sending of messages to handlers like this:
Message msg = Message.obtain();
msg.obj = // Some Arbitrary object
mHandler.sendMessage(msg);
I don't think the way you are doing this performs the Handler magic of data copy between threads because it's just running a Runnable.
EDIT: I am curious to see if this was the issue, so even if it wasn't could you respond in a comment and let me know the outcome?
EDIT 2: So it looks like your object is probably being stored as a local ref in the JNI Layer. Unfortunately, that's not good enough for your purposes, you may need to make it a global ref. Just be wary of the fact that if you do make it a global ref, you have to delete it yourself in native code when you are done with it.
http://developer.android.com/training/articles/perf-jni.html#local_and_global_references
Finally I solved problem by myself. The problem was, that when we make call from C++ to Java, SWIG proxy method passed pointer to it's argument to Java side. Something like:
void SwigDirector_NativeLayerDelegate::OnMessage(Message msg, Long answer_to) {
...
*((Message **)&jmsg) = &msg;
...
jenv->CallStaticVoidMethod(..., jmsg, ...);
...
}
On Java side another proxy method recieved pointer, wrapped it with Java representation of Message class and passed it to Java method OnMessage:
public static void SwigDirector_NativeLayerDelegate_OnMessage(
NativeLayerDelegate self, long msg, long answer_to) {
self.OnMessage(new Message(msg, false), answer_to);
// false parameter means that Message object isn't owner of 'msg' pointer, so it
// shouldn't free it on finalize.
}
After OnMessage finished, native Message object was destructed in SwigDirector_NativeLayerDelegate::OnMessage and Java Message object kept pointer to destructed native object.
Solution
I've wrote custom typemaps for my Message object:
%typemap(directorin,descriptor="L$packagepath/$javaclassname;") Message
%{*((Message**)&$input) = new Message($1);%}
%typemap(javadirectorin,descriptor="L$packagepath/$javaclassname;") Message
%{new Message($1, true)%}
Now SwigDirector_NativeLayerDelegate::OnMessage creates copy of msg and Java object owns it:
// Native
void SwigDirector_NativeLayerDelegate::OnMessage(Message msg, Long answer_to) {
...
*((Message**)&jmsg) = new Message(msg);
...
jenv->CallStaticVoidMethod(..., jmsg, ...);
...
}
// Java
public static void SwigDirector_NativeLayerDelegate_OnMessage(
NativeLayerDelegate self, long msg, long answer_to) {
self.OnMessage(new Message(msg, true), answer_to);
}
Related
So if I have a socket server, I can accept each socket and pass it to a executory
while(true){
Socket conn = socketServ.accept();
Runnable task = new Runnable() {
#Override
public void run() {
try{
server.executor(conn);
} catch(IOException e){
}
}
};
exec1.execute(task);
}
Doing this allows my server to run on my threads and does not block the same thread. Because I also have reference to that socket... called "conn" I can successfully return messages as well.
Now I have an RMI interface, which basically lets me call methods back and forth.
for example if I had this method:
public MusicServerResponseImpl CreatePlayerlist(String Name, UserObjectImpl uo) throws RemoteException {
MusicServerResponseImpl res = new MusicServerResponseImpl();
return res;
}
Which returns a serializable object. My concern is when this message gets called, I think it is going to get called in the main thread of the server, and thus will block that thread and slow down parallelism.
What I think is the solution is to have every single RMI method also create a task for an executor.. to speed up the execution of everything...this issue I am seeing however is unlike the socket where I have an object to send information back to, I am unsure how I would return a response from the RMI method, without somehow having to block the thread.
Does that make sense? Basically I am asking how I can execute in parallel with RMI methods while still being able to return results!
Thanks for the help!
Does that make sense?
No. Concurrent calls are natively supported.
See this documentation page and look for the property named maxConnectionThreads.
You could also have tested your assumptions by, for example, printing the current thread name in your server code, and trying to execute concurrent calls and see what happens.
I currently have a Matlab application which receives request from another, external application (coded in JAVA).
The Java application notify matlab using a system described in 'Undocumented Matlab by Yair Atlman. We can notify Matlab of various actions, name them A and B, which triggers different callbacks.
The problem is the following: In some condition, it is possible that the java application send a new notification before the first one is processed. In an ideal world, here is what I would like to happen:
Matlab receives A
Matlab starts executing callback A
Matlab receives B
Matlab holds callback B and continue executing callback A
Matlab executes callback B
Here is what happen:
Matlab receives A
Matlab starts executing callback A
Matlab receives B
Matlab pauses callback A
Matlab executes callback B
Matlab finishes callback A
I tried several possible solution but all failed and I finally managed to find a weird workaround, but this workaround came with issues and I have to get rid of it. I do not have access to parallel computing.
My tries involve storing received actions in a static queue and locking callback execution but it ends up in infinite loops since A is never cleared.
Since B could actually needs data produced by A, the perfect solution would actually be that Java holds the B notification until it receives a "complete" notification from Matlab. I tried to use parallelism here too but Matlab paused its execution and java never received the notification and sleeps forever ...
At this point I am willing to take any workaround because I am totally clueless for a robust solution.
Thanks
PS: Must work on both matlab 2011b and 2014b
Found solution using Matlab Control, a framework that allow you to communicate directly with Matlab while at the same time avoiding most of the potential deadlock issues:
https://code.google.com/archive/p/matlabcontrol/
And here is the class implementation I made to use the framework to fit my needs (many other usages are possible):
package framework.matlab.events;
import matlabcontrol.MatlabConnectionException;
import matlabcontrol.MatlabInvocationException;
import matlabcontrol.MatlabProxy;
import matlabcontrol.MatlabProxyFactory;
import matlabcontrol.MatlabProxyFactoryOptions;
public class MatlabEvent {
private String mMethodName;
private int mMethodOutputs;
private MatlabProxy mProxy;
public void setMethodParameters(String iMethodName, int iMethodOuputs) {
mMethodName = iMethodName;
mMethodOutputs = iMethodOuputs;
}
public void callMatlabMethod(Object ... obj) {
connect();
try {
mProxy.returningFeval(mMethodName, mMethodOutputs, obj);
} catch (MatlabInvocationException e) {
e.printStackTrace();
}
finally {
disconnect();
}
}
private void connect() {
MatlabProxyFactoryOptions options = new MatlabProxyFactoryOptions.Builder()
.setUsePreviouslyControlledSession(true)
.build();
MatlabProxyFactory factory = new MatlabProxyFactory(options);
try {
mProxy = factory.getProxy();
} catch (MatlabConnectionException e) {
e.printStackTrace();
}
}
private void disconnect() {
if (null != mProxy) {
mProxy.disconnect();
}
}
}
As a consequence, I am no longer using the Matlab notification system created by Yair Altman.
my project consists of 2 parts: server side and client side. When I start server side everything is OK, but when I start client side from time to time I get this error:
java.io.IOException: stream active
at java.io.ObjectOutputStream.reset(Unknown Source)
at client.side.TcpConnection.sendUpdatedVersion(TcpConnection.java:77)
at client.side.Main.sendCharacter(Main.java:167)
at client.side.Main.start(Main.java:121)
at client.side.Main.main(Main.java:60)
When I tried to run this project on the other pc this error occurred even more frequently. In Java docs I found this bit.
Reset may not be called while objects are being serialized. If called
inappropriately, an IOException is thrown.
And this is the function where error is thrown
void sendUpdatedVersion(CharacterControlData data) {
try {
ServerMessage msg = new ServerMessage(SEND_MAIN_CHARACTER);
msg.setCharacterData(data);
oos.writeObject(msg);
oos.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
I tried to put flush() but that didn't help. Any ideas? Besides, no errors on server side.
I think you're misunderstanding what reset() does. It resets the stream to disregard any object instances previously written to it. This is pretty clearly not what you want in your case, since you're sending an object to the stream and then resetting straight away, which is pointless.
It looks like all you need is a flush(); if that's insufficient then the problem is on the receiving side.
I think you are confusing close() with reset().
use
oos.close();
instead of oos.reset();
calling reset() is a perfectly valid thing to want to do. It is possible that 'data' is reused, or some field in data is reused, and the second time he calls sendUpdatedVersion, that part is not sent. So those who complain that the use is invalid are not accurate. Now as to why you are getting this error message
What the error message is saying is that you are not at the top level of your writeObject call chain. sendUpdatedVersion must be being called from an method that was called from another writeObject.
I'm assuming that some object is implementing a custom writeObject() and that method, is calling this method.
So you have to differentiate when sendUpdatedVersion is being called at the top level of the call chain and only use reset() in those cases.
I am using vertx in my project and I have problems with eventBus. If I understood right, it ables several languages to communicate using one string representing a server route. I have this code in my Server.java:
vertx.eventBus().registerHandler("getTree", new Handler<Message<String>>() {
public void handle(Message<String> e) {
// e.reply(call of function returning a json string);
}
});
In a javascript file, I need to get that json string just to print it for the moment. I have:
var eventBus = require('vertx/event_bus');
eventBus.send('getTree', '', function(reply) {
console.log('I received a reply ' + reply);
});
}
But nothing happens. Does anyone know why ?
I assume that you would like to see something like I received a reply in your console.
In order to be able to receive anything back to your JavaScript reply handler, you will need to change your Java message handler and call reply method on the incoming message e.g.
vertx.eventBus().registerHandler("getTree", new Handler<Message<String>>() {
public void handle(Message<String> msg) {
msg.reply("message from Java handler");
}
});
Without calling a reply method, nothing will happen in your JavaScript sender / reply receiver code.
After adding the mentioned change to your Java code you should be able to see following logs in console:
I received a reply message from Java handler
Note that even though you use different languages with Vert.x, entire logic is executed by JVM (JavaScript by Rhino open-source implementation).
Regarding Java NIO2.
Suppose we have the following to listen to client requests...
asyncServerSocketChannel.accept(null, new CompletionHandler <AsynchronousSocketChannel, Object>() {
#Override
public void completed(final AsynchronousSocketChannel asyncSocketChannel, Object attachment) {
// Put the execution of the Completeion handler on another thread so that
// we don't block another channel being accepted.
executer.submit(new Runnable() {
public void run() {
handle(asyncSocketChannel);
}
});
// call another.
asyncServerSocketChannel.accept(null, this);
}
#Override
public void failed(Throwable exc, Object attachment) {
// TODO Auto-generated method stub
}
});
This code will accept a client connection process it and then accept another.
To communicate with the server the client opens up an AsyncSocketChannel and fires the message.
The Completion handler completed() method is then invoked.
However, this means if the client wants to send another message on the same AsyncSocket instance it can't.
It has to create another AsycnSocket instance - which I believe means another TCP connection - which is performance hit.
Any ideas how to get around this?
Or to put the question another way, any ideas how to make the same asyncSocketChannel receive multipe CompleteionHandler completed() events?
edit:
My handling code is like this...
public void handle(AsynchronousSocketChannel asyncSocketChannel) {
ByteBuffer readBuffer = ByteBuffer.allocate(100);
try {
// read a message from the client, timeout after 10 seconds
Future<Integer> futureReadResult = asyncSocketChannel.read(readBuffer);
futureReadResult.get(10, TimeUnit.SECONDS);
String receivedMessage = new String(readBuffer.array());
// some logic based on the message here...
// after the logic is a return message to client
ByteBuffer returnMessage = ByteBuffer.wrap((RESPONSE_FINISHED_REQUEST + " " + client
+ ", " + RESPONSE_COUNTER_EQUALS + value).getBytes());
Future<Integer> futureWriteResult = asyncSocketChannel.write(returnMessage);
futureWriteResult.get(10, TimeUnit.SECONDS);
} ...
So that's it my server reads a message from the async channe and returns an answer.
The client blocks until it gets the answer. But this is ok. I don't care if client blocks.
Whent this is finished, client tries to send another message on same async channel and it doesn't work.
There are 2 phases of connection and 2 different kind of completion handlers.
First phase is to handle a connection request, this is what you have programmed (BTW as Jonas said, no need to use another executor). Second phase (which can be repeated multiple times) is to issue an I/O request and to handle request completion. For this, you have to supply a memory buffer holding data to read or write, and you did not show any code for this. When you do the second phase, you'll see that there is no such problem as you wrote: "if the client wants to send another message on the same AsyncSocket instance it can't".
One problem with NIO2 is that on one hand, programmer have to avoid multiple async operations of the same kind (accept, read, or write) on the same channel (or else an error occur), and on the other hand, programmer have to avoid blocking wait in handlers. This problem is solved in df4j-nio2 subproject of the df4j actor framework, where both AsyncServerSocketChannel and AsyncSocketChannel are represented as actors. (df4j is developed by me.)
First, you should not use an executer like you have in the completed-method. The completed-method is already handled in a new worker-thread.
In your completed-method for .accept(...), you should call asychSocketChannel.read(...) to read the data. The client can just send another message on the same socket. This message will be handled with a new call to the completed-method, perhaps by another worker-thread on your server.