JNI byteArray passing help - c

I have been running into issues with my Android app closing (no errors or anything) when trying to execute the following code:
JNIEXPORT void Java_teamjeff_oggstreamtest_MainTest_audioFunc(JNIEnv* env, jobject obj) {
//<REMOVED VARIABLE INITIALIZATION>
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID writeDataFunc = (*env)->GetMethodID(env, cls, "writeToAudioTrack", "([B)V");
if (!writeDataFunc) return;
jmethodID readDataFunc = (*env)->GetMethodID(env, cls, "readFromBuffer", "([B)I");
if (!readDataFunc) return;
rawDataRead = (*env)->NewByteArray(env, 4096);
bytes = (*env)->CallIntMethod(env, obj,readDataFunc, &rawDataRead);
char* carr = (*env)->GetByteArrayElements(env, rawDataRead, NULL);
memcpy(buffer, carr, bytes);
(*env)->DeleteLocalRef(env, rawDataRead);
//<REMOVED REST OF FUNCTION>
}
I've tracked the "trouble" code to the bytes = (*env)->CallIntMethod(env, obj,readDataFunc, &rawDataRead); line. If I return before this line, my app doesn't close, but if I return immediately after this line, my app closes randomly without even an error.
Here is the JAVA code:
package teamjeff.oggstreamtest;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import com.Ostermiller.util.CircularByteBuffer;
public class MainTest extends Activity {
public static Handler mHandler = new Handler();
private final CircularByteBuffer cbb = new CircularByteBuffer(1024*512, true);
public AudioTrack mAudioTrack;
static {
System.loadLibrary("vorbis-decoder");
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final Socket test = new Socket(InetAddress.getByName(<HOME SERVER URL>), <PORT>);
new Thread(
new Runnable(){
public void run(){
try {
while(!test.isClosed()) {
byte[] temp = new byte[4096];
int bytes = test.getInputStream().read(temp, 0, 4096);
cbb.getOutputStream().write(temp, 0, bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
).start();
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
1024*64,
AudioTrack.MODE_STREAM);
mAudioTrack.play();
new Thread(new Runnable() {
public void run() {
audioFunc();
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
public native void audioFunc();
#SuppressWarnings("unused")
private void writeToAudioTrack(final byte[] media) {
mHandler.post(new Runnable() {
public void run() {
mAudioTrack.write(media, 0, media.length);
}
});
}
#SuppressWarnings("unused")
private int readFromBuffer(byte[] buffer) {
try {
return cbb.getInputStream().read(buffer, 0, buffer.length);
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}
}
I have searched for days here and on Google on how to accomplish what I want to do. My code above is the gluing together of various code snippets I've found around the internet with tweaks to fit my use-case.
What I'm trying to accomplish:
I will read in data from a socket in my Android App, pass this data to my C code for decoding (though the algorithm reads it in piece by piece during the algorithm, meaning I can't pass in the byteArray from Java to C and call my C function multiple times since the decoder sometimes uses data from previous read-in bytes). My C code does the decoding, and passes the PCM data back to my Android app to be played on an AudioTrack.
I am using a circular buffer to buffer in the data from the socket.
When I try to debug my Android App, I set break points at the entries to both the read and write functions and they never seem to be called.
Am I doing something wrong when I pass the byteArray from my C code to JAVA to be filled with data? Should I be doing this an alternative way?

A few notes that might help.
&rawDataRead is wrong. Lose the &. You just pass the ref that you get, not the address of it.
you don't need to delete that local ref. All local refs are deleted when a native function returns. I'm fairly confident that this is true in java, but the android situation may be different.
You don't have to keep retrieving the method ids. You can get them once and hang onto them.

Related

Integration testing flink job

I've written a small flink application. I has some input, and enriches it with data from an external source. It's an RichAsyncFunction and within the open method I construct a http client to be used for the enrichment.
Now I want to write an integration test for my job. But since the http client is created within the open method I have no means to provide it, and mock it in my integration test. I've tried to refactor it providing it within the constructor, but I'm always getting serialisation errors.
This is the example I'm working from:
https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/stream/operators/asyncio.html
Thanks in advance :)
This question was posted over a year ago but I'll post the answer in-case anyone stumbles upon this in the future.
The serialization exception you are seeing is likely this
Exception encountered when invoking run on a nested suite. *** ABORTED *** (610 milliseconds)
java.lang.NullPointerException:
at java.util.Objects.requireNonNull(Objects.java:203)
at org.apache.flink.streaming.runtime.streamrecord.StreamElementSerializer.<init>(StreamElementSerializer.java:64)
at org.apache.flink.streaming.api.operators.async.AsyncWaitOperator.setup(AsyncWaitOperator.java:136)
at org.apache.flink.streaming.api.operators.SimpleOperatorFactory.createStreamOperator(SimpleOperatorFactory.java:77)
at org.apache.flink.streaming.api.operators.StreamOperatorFactoryUtil.createOperator(StreamOperatorFactoryUtil.java:70)
at org.apache.flink.streaming.util.AbstractStreamOperatorTestHarness.setup(AbstractStreamOperatorTestHarness.java:366)
at org.apache.flink.streaming.util.OneInputStreamOperatorTestHarness.setup(OneInputStreamOperatorTestHarness.java:165)
...
The reason is that your test operator needs to know how to deserialize the DataStream input type. The only way to provide this is by supplying it directly while initializing the testHarness and then passing it to the setup() method call.
So to test the example from the Flink docs you linked you can do something like this (my implementation is in Scala but you can adapt it to Java as well)
import org.apache.flink.api.common.ExecutionConfig
import org.apache.flink.api.java.typeutils.TypeExtractor
import org.apache.flink.configuration.Configuration
import org.apache.flink.streaming.api.datastream.AsyncDataStream.OutputMode
import org.apache.flink.streaming.api.operators.async.AsyncWaitOperator
import org.apache.flink.streaming.runtime.tasks.{StreamTaskActionExecutor, TestProcessingTimeService}
import org.apache.flink.streaming.runtime.tasks.mailbox.{MailboxExecutorImpl, TaskMailboxImpl}
import org.apache.flink.streaming.util.OneInputStreamOperatorTestHarness
import org.scalatest.{BeforeAndAfter, FunSuite, Matchers}
/**
This test case is written using Flink 1.11+.
Older versions likely have a simpler constructor definition for [[AsyncWaitOperator]] so you might have to remove the last two arguments (processingTimeService and mailboxExecutor)
*/
class AsyncDatabaseRequestSuite extends FunSuite with BeforeAndAfter with Matchers {
var testHarness: OneInputStreamOperatorTestHarness[String, (String, String)] = _
val TIMEOUT = 1000
val CAPACITY = 1000
val MAILBOX_PRIORITY = 0
def createTestHarness: Unit = {
val operator = new AsyncWaitOperator[String, (String, String)](
new AsyncDatabaseRequest {
override def open(configuration: Configuration): Unit = {
client = new MockDatabaseClient(host, post, credentials); // put your mock DatabaseClient object here
}
},
TIMEOUT,
CAPACITY,
OutputMode.UNORDERED,
new TestProcessingTimeService,
new MailboxExecutorImpl(
new TaskMailboxImpl,
MAILBOX_PRIORITY,
StreamTaskActionExecutor.IMMEDIATE
)
)
// supply the TypeSerializer for the "input" type of the operator
testHarness = new OneInputStreamOperatorTestHarness[String, (String, String)](
operator,
TypeExtractor.getForClass(classOf[String]).createSerializer(new ExecutionConfig)
)
// supply the TypeSerializer for the "output" type of the operator to the setup() call
testHarness.setup(
TypeExtractor.getForClass(classOf[(String, String)]).createSerializer(new ExecutionConfig)
)
testHarness.open()
}
before {
createTestHarness
}
after {
testHarness.close()
}
test("Your test case goes here") {
// fill in your test case here
}
}
Here is the solution in Java
class TestingClass {
#InjectMocks
ClassUnderTest cut;
private static OneInputStreamOperatorTestHarness<IN, OUT> testHarness; // replace IN, OUT with your asyncFunction's
private static long TIMEOUT = 1000;
private static int CAPACITY = 1000;
private static int MAILBOX_PRIORITY = 0;
private long UNUSED_TIME = 0L;
Driver driverRef;
public void createTestHarness() throws Exception {
cut = new ClassUnderTest() {
#Override
public void open(Configuration parameters) throws Exception {
driver = mock(Driver.class); // mock your driver (external data source here).
driverRef = driver; // create external ref to driver to refer to in test
}
};
MailboxExecutorImpl mailboxExecutorImpl = new MailboxExecutorImpl(
new TaskMailboxImpl(), MAILBOX_PRIORITY, StreamTaskActionExecutor.IMMEDIATE
);
AsyncWaitOperator operator = new AsyncWaitOperator<>(
gatewayEnrichment,
TIMEOUT,
CAPACITY,
ORDERED,
new TestProcessingTimeService(),
mailboxExecutorImpl
);
testHarness = new OneInputStreamOperatorTestHarness<IN, OUT>(
operator,
TypeExtractor.getForClass(IN.class).createSerializer(new ExecutionConfig())
);
testHarness.setup(TypeExtractor.getForClass(OUT.class).createSerializer(new ExecutionConfig()));
testHarness.open();
}
#BeforeEach()
void setUp() throws Exception {
createTestHarness();
MockitoAnnotations.openMocks(this);
}
#AfterEach
void tearDown() throws Exception {
testHarness.close();
}
#Test
public void test_yourTestCase() throws Exception {
}
}

Tomcat executor with runnable while(true) loop is only run once. Why?

I am trying to implement a javax.mail.event.MessageCountListener in Tomcat. When I start the application the contextInitialized method seems to run and the mailbox is read. However, I see the log message "Idling" only once. I would expect that it would idle constantly and invoke the AnalyzerService() when an email is received or deleted.
Update: Found that the idle() method is not returning. It runs untill com.sun.mail.iap.ResponseInputStream.readResponse(ByteArray ba) method where it runs into a while loop where it never gets out.
Am I misusing the idle() method for something I should not do? Is this a bug in com.sun.mail.iap package?
The AnalyzerContextListener.java:
import com.sun.mail.imap.IMAPStore;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.event.MessageCountListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class AnalyzerContextListener implements ServletContextListener {
private ExecutorService executorService;
private final String username = "myemail#gmail.com";
private final String password = "mypassword";
private final String mailhost = "imap.gmail.com";
private final String foldername = "INBOX";
#Override
public void contextInitialized(ServletContextEvent sce) {
final ServletContext servletContext = sce.getServletContext();
executorService = Executors.newFixedThreadPool(3);
Session session = Session.getInstance(new Properties());
try {
final IMAPStore store = (IMAPStore) session.getStore("imaps");
store.connect(mailhost, username, password);
final Folder folder = store.getFolder(foldername);
if (folder == null) {
servletContext.log("Folder in mailbox bestaat niet.");
return;
}
folder.open(Folder.READ_ONLY);
MessageCountListener countListener = new AnalyzerService();
folder.addMessageCountListener(countListener);
Runnable runnable = new Runnable() {
#Override
public void run() {
while (true) {
try {
servletContext.log("Aantal berichten in folder: " + folder.getMessageCount());
servletContext.log("Idling");
store.idle();
} catch (MessagingException ex) {
servletContext.log(ex.getMessage());
return;
}
}
}
};
executorService.execute(runnable);
servletContext.log("Executorservice gestart");
} catch (MessagingException ex) {
servletContext.log(ex.getMessage());
}
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
sce.getServletContext().log("Context wordt vernietigd");
executorService.shutdown();
sce.getServletContext().log("Executorservice gestopt");
}
}
The AnalyzerService.java:
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.event.MessageCountEvent;
import javax.mail.event.MessageCountListener;
class AnalyzerService implements MessageCountListener {
public AnalyzerService() {
}
#Override
public void messagesAdded(MessageCountEvent event) {
Message[] addedMessages = event.getMessages();
for (Message message : addedMessages) {
try {
System.out.println(message.getSubject());
} catch (MessagingException ex) {
System.out.println(ex.getMessage());
}
}
}
#Override
public void messagesRemoved(MessageCountEvent event) {
Message[] removedMessages = event.getMessages();
for (Message message : removedMessages) {
try {
System.out.println(message.getSubject());
} catch (MessagingException ex) {
System.out.println(ex.getMessage());
}
}
}
}
while (true) {
try {
servletContext.log("Aantal berichten in folder: " + folder.getMessageCount());
servletContext.log("Idling");
store.idle();
} catch (MessagingException ex) {
servletContext.log(ex.getMessage());
return;
}
}
has exactly 2 3 possibilities to end earlier than never run only once.
The loop actually ends either:
Through the explicit return in case of a MessagingException. Look at your logs, there either a message or something strange like "null". Consider using a proper stacktrace log (.log(String message, Throwable throwable)) since Exception#getMessage() is often empty or not telling you much.
Through any unchecked exception. You should notice that in some log though since uncaught exceptions via executorService.execute should invoke the nearest uncaught exeption handler which is generally bad. See Choose between ExecutorService's submit and ExecutorService's execute
The loop stops executing after it logs "Idling"
store.idle() never returns. (every other line of code could do that theoretically as well, e.g. the folder.getMessageCount() call in a 2nd iteration but that's very unlikely)
Regarding No 3 - the documentation
Use the IMAP IDLE command (see RFC 2177), if supported by the server, to enter idle mode so that the server can send unsolicited notifications without the need for the client to constantly poll the server. Use a ConnectionListener to be notified of events. When another thread (e.g., the listener thread) needs to issue an IMAP comand for this Store, the idle mode will be terminated and this method will return. Typically the caller will invoke this method in a loop.
If the mail.imap.enableimapevents property is set, notifications received while the IDLE command is active will be delivered to ConnectionListeners as events with a type of IMAPStore.RESPONSE. The event's message will be the raw IMAP response string. Note that most IMAP servers will not deliver any events when using the IDLE command on a connection with no mailbox selected (i.e., this method). In most cases you'll want to use the idle method on IMAPFolder.
That sounds like this method is not designed to return any time soon. In your case never since you don't issue any commands towards the server after you enter idle. Besides that
folder.idle() could be what you should actually do
I guess the documentation is wrong, however ConnectionListener and MessageCountListener are two different things.

Exiting game loop in JavaME freezes system

I am working on developing JavaME games and am using an LG500G and Motorola EM326g as testing devices. At this very early stage, things are going wrong. I have a while(!stop){} game loop, and at a certain point a method will set stop to true, which will enter a block of code after the while loop, a sort of end-game condition. This always works fine in the emulator, in the various ways I have expressed it. However, I have never been able to get it to work on either of the phones. Instead, the game freezes and no further activity happens. The baffling thing is that when I compile code from other games I have studied which use the same looping mechanism, those games run as expected! What could I be doing wrong? Is there a way I could rephrase the code to get it to work? I am currently looking at a "game state manager" as a possible solution...but something as simple as this should just work!(by the way, I tried a simple while(!stop){} loop, but had to try an if(!stop){}else{} block within the while(true) loop. It did not work on the phones either:
import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.*;
public class GardenGameCanvas extends GameCanvas implements Runnable{
private Image tomato;
private Sprite tomatoSprite;
private boolean stop;
private int tomX;
private int tomY;
private LayerManager manager;
public GardenGameCanvas(){
super(false);
}
public void start() {
try{
tomato = Image.createImage("/tomato.png");
tomatoSprite = new Sprite(tomato, 16, 16);
tomX= 0;
tomY = getHeight()/2;
manager = new LayerManager();
manager.append(tomatoSprite);
stop = false;
}catch(IOException ioex){System.err.println(ioex);}
Thread runner = new Thread(this);
runner.start();
}
public void run() {
while(true){
if(!stop){
verifyGame();
checkInput();
update(getGraphics());
try {
Thread.currentThread().sleep(30);
} catch(Exception e) {}
}else{
endGame(getGraphics());
}
}
}
private void update (Graphics g){
g.setColor(0xFFFFFF); //white
g.fillRect(0, 0, getWidth(), getHeight());
buildGame(g);
tomatoSprite.setPosition(tomX, tomY);
manager.paint(g, 0, 0);
flushGraphics();
}
private void buildGame(Graphics g){
g.setColor(0x000000);
g.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);
}
private void checkInput(){
int keyStates = getKeyStates();
if((keyStates & LEFT_PRESSED) != 0) {
tomX -= 1;
}
else if((keyStates & RIGHT_PRESSED) != 0) {
tomX += 1;
}
}
private void endGame(Graphics g){
g.setColor(0xFFFFFF);
g.fillRect(0,0,getWidth(), getHeight());
g.setColor(0x000000);
g.drawString("Game Over", getWidth()/2, getHeight()/2, Graphics.HCENTER);
flushGraphics();
}
private void verifyGame(){
if(tomX==getWidth()){
stop = true;
return;
}
}
}
I think the following is the problem:
You are never ending the while-loop.
Emulator and device are handling threads an processes differently. Probably your run-thread takes all the time on the device.
Try for example the following:
while (true){
if(!stop){
....
}
else {
endGame();
return;
}
}

ChannelFactory method call increse memory

I have an winform application which consumes windows service, i user ChannelFactory
to connect to service, problem is when i call service method using channel the memory usage increase and after
method execute memory not go down(even after form close), i call GC.Collect but no change
channel Create class
public class Channel1
{
List<ChannelFactory> chanelList = new List<ChannelFactory>();
ISales salesObj;
public ISales Sales
{
get
{
if (salesObj == null)
{
ChannelFactory<ISales> saleschannel = new ChannelFactory<ISales>("SalesEndPoint");
chanelList.Add(saleschannel);
salesObj = saleschannel.CreateChannel();
}
return salesObj;
}
}
public void CloseAllChannels()
{
foreach (ChannelFactory chFac in chanelList)
{
chFac.Abort();
((IDisposable)chFac).Dispose();
}
salesObj = null;
}
}
base class
public class Base:Form
{
public Channel1 channelService = new Channel1();
public Channel1 CHANNEL
{
get
{
return channelService;
}
}
}
winform class
Form1:Base
private void btnView_Click(object sender, EventArgs e)
{
DataTable _dt = new DataTable();
try
{
gvAccounts.AutoGenerateColumns = false;
_dt = CHANNEL.Sales.GetDatatable();
gvAccounts.DataSource = _dt;
}
catch (Exception ex)
{
MessageBox.Show("Error Occurred while processing...\n" + ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
finally
{
CHANNEL.CloseAllChannels();
_dt.Dispose();
//GC.Collect();
}
}
You're on the right track in terms of using ChannelFactory<T>, but your implementation is a bit off.
ChannelFactory<T> creates a factory for generating channels of type T. This is a relatively expensive operation (as compared to just creating a channel from the existing factory), and is generally done once per life of the application (usually at start). You can then use that factory instance to create as many channels as your application needs.
Generally, once I've created the factory and cached it, when I need to make a call to the service I get a channel from the factory, make the call, and then close/abort the channel.
Using your posted code as a starting point, I would do something like this:
public class Channel1
{
ChannelFactory<ISales> salesChannel;
public ISales Sales
{
get
{
if (salesChannel == null)
{
salesChannel = new ChannelFactory<ISales>("SalesEndPoint");
}
return salesChannel.CreateChannel();
}
}
}
Note that I've replaced the salesObj with salesChannel (the factory). This will create the factory the first time it's called, and create a new channel from the factory every time.
Unless you have a particular requirement to do so, I wouldn't keep track of the different channels, especially if follow the open/do method/close approach.
In your form, it'd look something like this:
private void btnView_Click(object sender, EventArgs e)
{
DataTable _dt = new DataTable();
try
{
gvAccounts.AutoGenerateColumns = false;
ISales client = CHANNEL.Sales
_dt = client.GetDatatable();
gvAccounts.DataSource = _dt;
((ICommunicationObject)client).Close();
}
catch (Exception ex)
{
((ICommunicationObject)client).Abort();
MessageBox.Show("Error Occurred while processing...\n" + ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
The code above gets a new ISales channel from the factory in CHANNEL, executes the call, and then closes the channel. If an exception happens, the channel is aborted in the catch block.
I would avoid using Dispose() out of the box on the channels, as the implementation in the framework is flawed and will throw an error if the channel is in a faulted state. If you really want to use Dispose() and force the garbage collection, you can - but you'll have to work around the WCF dispose issue. Google will give you a number of workarounds (google WCF Using for a start).

WP7 Audio Streaming Help

So I've downloaded the samples from http://archive.msdn.microsoft.com/ManagedMediaHelpers.
I've got my code working using MP3MediaStreamSource. However, I don't fully understand the code would like some explanation.
public partial class MainPage : PhoneApplicationPage
{
private static string mediaFileLocation = "http://file-here.mp3";
private static HttpWebRequest request = null;
private static Mp3MediaStreamSource mss = null;
public MainPage()
{
InitializeComponent();
}
private void RequestCallback(IAsyncResult asyncResult)
{
HttpWebResponse response = request.EndGetResponse(asyncResult) as HttpWebResponse;
Stream s = response.GetResponseStream();
mss = new Mp3MediaStreamSource(s, response.ContentLength);
Deployment.Current.Dispatcher.BeginInvoke(
() =>
{
this.wp7AudioElement.Volume = 100;
this.wp7AudioElement.SetSource(mss);
});
}
private void Button_Click(object sender, RoutedEventArgs e)
{
request = WebRequest.CreateHttp(MainPage.mediaFileLocation);
// NOTICE
// Makes this demo code easier but I wouldn't do this on a live phone as it will cause the whole
// file to download into memory at once.
//
// Instead, use the asynchronous methods and read the stream in the backgound and dispatch its
// data as needed to the ReportGetSampleCompleted call on the UIThread.
request.AllowReadStreamBuffering = true;
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(this.RequestCallback), null);
}
}
It's really just the last method I need explained, I don't understand the Notice as to why it's a bad idea and how to do it differently?
Basically, it is trying to tell you that you are downloading 1 file COMPLETELY before it plays. It is not a good idea, since if the file is 10 MB, it may take a while before it completely downloads.
A better idea would be to chunk the file using Encoders, and read it in on need basis.

Resources