I keep getting this error when I run my app. The app will compile fine and interaction with the app is normal and until a certain period it will come up with the OUTOFMEMORY error message.
Error Logcat:
E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
at java.lang.StringBuilder.append(StringBuilder.java:216)
at org.json.JSONStringer.value(JSONStringer.java:249)
at org.json.JSONArray.writeTo(JSONArray.java:572)
at org.json.JSONStringer.value(JSONStringer.java:233)
at org.json.JSONObject.writeTo(JSONObject.java:671)
at org.json.JSONObject.toString(JSONObject.java:640)
at com.android.volley.toolbox.JsonObjectRequest.<init>(JsonObjectRequest.java:47)
at com.apps.robotapp.RobotService.onStart(RobotService.java:75)
at android.app.Service.onStartCommand(Service.java:450)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2833)
at android.app.ActivityThread.access$2000(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1419)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
at dalvik.system.NativeStart.main(Native Method)
At Java:75 (RobotService:onStart) where the error occurs:
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,SPHERE_URL,obj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//System.out.println("JsonObjectRequest:>>" + response + "<<");
System.out.println(response);
//hideProgressDialog();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//hideProgressDialog();
Runtime.getRuntime().gc();
}
}); queue.add(jsObjRequest);
I have implemented both system.gc() and Runtime.getRuntime().gc() into my implementation, however it still doesn't work.
Any idea how can I tackle this issue? Thanks
Without getting into the code.
You can follow ref count and RAM consumption :
http://developer.android.com/tools/debugging/debugging-memory.html
Btw. don't you have "Caused by..." in the exception log ?
Apart from using inordinate amounts of memory, this can happen when you leak memory. Leaking is unintentionally keeping references to objects that you do not need anymore.
There are many ways this can happen. The most obvious one is never clearing old items from a cache. In Android you can have Context related memory leaks, but that may not be the case for you.
Have a look at Google I/O 2011: Memory Management for Android Apps for a crash course on memory. In the video there's a link to the Eclipse Memory Analysis Tool (MAT) which can help you zoom in on the problem. Mastering this will likely take quite some time, so you may just want to watch the video to get an understanding of memory leaks and then using your common sense and knowledge of your app find the leak by reasoning. Good luck!
Related
I use ExecutorService. but sometimes occur OutOfMemoryError
error log.
java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Native Method)
at java.lang.Thread.start(Thread.java:1063)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:921)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339)
at kr.co.iosystem.blackeyeonandroid.m4m.domain.CapturePipeline.executeProcessor(CapturePipeline.java:195)
at kr.co.iosystem.blackeyeonandroid.m4m.domain.CapturePipeline.start(CapturePipeline.java:156)
at kr.co.iosystem.blackeyeonandroid.record.VideoCapture.start(VideoCapture.java:92)
at kr.co.iosystem.blackeyeonandroid.record.Capturing.startCapturing(Capturing.java:97)
at kr.co.iosystem.blackeyeonandroid.record.RecTimerHandler.startRecording(RecTimerHandler.java:221)
at kr.co.iosystem.blackeyeonandroid.record.RecTimerHandler.handleMessage(RecTimerHandler.java:83)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5415)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
and my source
protected ExecutorService pools;
public void start() {
pools = Executors.newCachedThreadPool();
executeProcessor();
}
protected void executeProcessor() {
pools.execute(new Runnable() {
#Override
public void run() {
...
}
}
}
first, pools = Executors.newCachedTheadPool(); previously pools = Executors.newSingleThreadExecutor();
usually, this situation. how to fix OutOfMemory when I use ExecutorService on android?
if you know this problem. please advice for me
thanks
The cachedThreadPoolExecutor() will create a potentially unbounded (infinite) number of threads given new tasks. I am not sure what you have included in you run() method, however if it has a for loop/while loop or any other mechanism that spawns new work, it will automatically create a new thread costing you memory. This is what could potentially lead you to the OutOfMemoryException you are receiving.
To diagnose, try using a fixedThreadPool(int numOfThreads) with a low (bounded) number of threads e.g. 4 and see if you still get the error.
If yes, then consider what the run method is doing to consume memory
If no, then you now know that the number of threads the cachedThreadPoolExecutor() was creating was problematic, try decompose your tasks to use fewer threads. Try finding that sweet spot of thread count/ memory usage/ performance , this kind of stuff is usually about management and there rarely is a one-size fits all approach.
I am using version 1.2.1 (tried with latest version 1.2.2) of android's youtube player api. It works fine on most of the devices. However now and then, I keep on getting crashes on crashlytics. I am getting the following crashes
Fatal Exception: java.lang.IllegalStateException: android.os.TransactionTooLargeException
at com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer.x(SourceFile:558)
at bpd.w(SourceFile:576)
at tef.onTransact(SourceFile:390)
at android.os.Binder.transact(Binder.java:395)
at com.google.android.youtube.player.internal.d$a$a.r(Unknown Source)
at com.google.android.youtube.player.internal.s.h(Unknown Source)
at com.google.android.youtube.player.YouTubePlayerView.e(Unknown Source)
at com.google.android.youtube.player.YouTubePlayerSupportFragment.onSaveInstanceState(Unknown Source)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1936)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1654)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1722)
at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1938)
at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1654)
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1722)
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:527)
at com.newshunt.news.activities.NewsBaseActivity.onSaveInstanceState(NewsBaseActivity.java:56)
at com.newshunt.news.activities.NewsDetailsActivity.onSaveInstanceState(NewsDetailsActivity.java:613)
at android.app.Activity.performSaveInstanceState(Activity.java:1388)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1286)
at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:4588)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3960)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4023)
at android.app.ActivityThread.access$1200(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1498)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Also getting crashes for the following exception.
Fatal Exception: java.lang.IllegalStateException: android.os.DeadObjectException
at com.google.android.apps.youtube.api.jar.a.eo.surfaceDestroyed(SourceFile:236)
at android.view.SurfaceView.updateWindow(SurfaceView.java:589)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:237)
at android.view.View.dispatchDetachedFromWindow(View.java:12854)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2757)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2757)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3844)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3819)
at android.view.ViewGroup.removeView(ViewGroup.java:3751)
at com.google.android.youtube.player.YouTubePlayerView$1.b(Unknown Source)
at com.google.android.youtube.player.internal.r.h(Unknown Source)
at com.google.android.youtube.player.internal.r$e.onServiceDisconnected(Unknown Source)
at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1111)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1125)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5317)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(NativeStart.java)
The crash happens to appear in specific versions of youtube application like 5.2.27. Although there are a lot of issues filed for these crashes, there has been no reply from the youtube developers on how to mitigate this issue.
Some of the fellow developers have suggested the following workarounds
1) Use loadVideo instead of cueVideo. But I cannot use this workaround because loadVideo always autoplays the video which is not a requirement of my application. Also someone mentioned that with loadVideo also, this problem is happening although in some different version.
2) Put check in the code to check the youtube application version and then put the specific code. Now the problem with this approach is that I have to check each and every version of youtube app ever released and check which versions are causing the issue which is not a good workaround.
Now is there any fix which I can apply to avoid this issue or are the youtube developers planning to release some jar which internally takes care of all these issues?
I reduced the bug occurrence by putting youtube calls (like youtubePlayer.loadVideo(), cueVideo(), getCurrentTimeMillis() etc.) in a try catch block and catch the IllegalStateException exception then reinitialize youtube player.
To create a new instance of the YoutubePlayer just call the initialize() method in the catch block.
Example:
if (youtubePlayer != null) {
try {
youtubePlayer.loadVideo(videoId);
} catch (IllegalStateException e) {
initialize(API_KEY, this);
}
}
but the bug still occurred , I worked around it by catching these exceptions and restart activity. This uncaught exceptions and to catch them you need to use UncaughtExceptionHandler
example :
private Thread.UncaughtExceptionHandler defaultUEH;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
// setup handler for uncaught exception
Thread.setDefaultUncaughtExceptionHandler(_unCaughtExceptionHandler);
}
private Thread.UncaughtExceptionHandler _unCaughtExceptionHandler =
new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e(TAG, "uncaughtException: ", ex);
PendingIntent myActivity = PendingIntent.getActivity(getApplicationContext(),
192837, new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager;
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
15000, myActivity );
System.exit(2);
// re-throw critical exception further to the os (important)
defaultUEH.uncaughtException(thread, ex);
}
};
The android YouTube Player API is not stable, there are known bugs in it. The team from YouTube said that they will release a new version of the library.
For now, the best solution I have found is to build my own library.
Following the suggestions provided in this question I modified my AdMob code to be compliant with the recommendations, that effectively worked reducing the number of exceptions that were appearing. However a new exception is rising.
The code is the following:
#Override
protected void onDestroy() {
if ( adView != null ) {
adView.destroy();
adView = null;
Log.i(ApplicationData.APP_TAG, TAG + ": OnDestroy, destroying the Adview");
}
super.onDestroy();
}
The method adView.destroy() appears to work well as the LogCat message is published. Just after this message I am getting the following exception on WebView:
java.lang.NullPointerException
at android.webkit.WebViewClassic.loadDataWithBaseURL(WebViewClassic.java:2741)
at android.webkit.WebView.loadDataWithBaseURL(WebView.java:919)
at com.google.android.gms.ads.internal.request.n.run(SourceFile:206)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5297)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Unfourtunately I am not able to find a way to reproduce the problem but is happening in production regularly. I have not been able to find any problem, has somebody any hint of what I can do?
One of Google Mobile Ads SDK Team said (March 14),
We looked into this issue when it was first reported, and a fix has been released within Google Play services. You should see fewer and fewer instances as your users' devices update to the new version.
Refer to https://groups.google.com/forum/#!topic/google-admob-ads-sdk/oYpQI_L14Tg
This occurs when the WebView is destroyed before loadDataWithBaseUrl is called( probably by other thread). In AdMob code, i saw that they handle this now as follows
public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) {
synchronized(this) {
if(!this.isDestroyed()) {
super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
} else {
Log.d("The webview is destroyed. Ignoring action.");
}
}
}
So it should not occur now.
I need to access a MySQL db from my android app. Now all the work is done through
DriverManager.getConnection(url);
and so on. But I have to access the db from multiple threads, so I have to use connection pooling.
Question 1. Is
com.mysql.jdbc.jdbc2.optional.MysqlDataSource ds = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();
the right way of creating the data source?
Question 2. If I write the previous line of code, my app compiles and installs on the device (not emulator) fine, but I get a weird
java.lang.NoClassDefFoundError: com.mysql.jdbc.jdbc2.optional.MysqlDataSource`
, that I can't catch with a try/catch handler:
try
{
com.mysql.jdbc.jdbc2.optional.MysqlDataSource a = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();
}
catch (Exception e)
{
I don't get here. The app just crashes, as if I had no try/catch block.
}
Question 3. I copied mysql-connector-java-5.1.20-bin.jar to the device and wrote the following code:
try
{
final String str = Environment.getExternalStorageState();
final File sd = getActivity().getExternalFilesDir(null);
final File file = new File(sd, "mysql-connector-java-5.1.20-bin.jar");
boolean b = file.exists();
final URLClassLoader cl = URLClassLoader.newInstance(new URL[] {file.toURI().toURL()} );
cl.loadClass("com.mysql.jdbc.jdbc2.optional.MysqlDataSource"); //$NON-NLS-1$
}
catch (Exception e)
{
new AlertDialog.Builder(getActivity())
.setMessage(ObjectConverter.throwable2String(e))
.show();
}
The file is found but
cl.loadClass()
fails with
java.lang.NullPointerException
at java.net.URLClassLoader.getPermissions(URLClassLoader.java:614)
at java.security.SecureClassLoader.getPD(SecureClassLoader.java:140)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:93)
at java.net.URLClassLoader.access$600(URLClassLoader.java:55)
at java.net.URLClassLoader$URLJarHandler.createClass(URLClassLoader.java:364)
at java.net.URLClassLoader$URLJarHandler.findClass(URLClassLoader.java:303)
at java.net.URLClassLoader.findClass(URLClassLoader.java:748)
at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
at ru.mypkg.myapp.func(myapp.java:367)
at android.view.View.performClick(View.java:3511)
at android.view.View$PerformClick.run(View.java:14110)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Any help greatly appreciated.
This question is 6 years old and Mark is correct that, in almost every scenario you can think of, JDBC on Android is about as sensible as trying to use a toaster in the bath. However, sometimes we do things because we can and not because we necessarily should, and today I had a justifiable reason to want to do this (for a specific very niche app running in an unusual environment), which is how I found this question.
Addressing the NoClassDefFoundError first, the reason it isn't caught by the catch block is because it's an Error not an Exception. Both Error and Exception inherit from Throwable, so you could catch that instead:
catch (Throwable t)
{
// This will catch NoClassDefFoundError
}
I believe that it's not MySqlDataSource that it can't find, but one of the classes or interfaces that it depends on - in my case it was javax.naming.Referenceable. Android doesn't provide the javax.naming package so trying to use the pooling features of the Connector/J JDBC driver for MySQL isn't going to get you very far (you could try to provide the missing dependencies but that road likely leads to madness).
Instead you'll probably have more luck with a third-party connection pool implementation. There are various Java libraries for doing this. Some of them will work on Android. One that I have verified does work is HikariCP. There are instructions for configuring it here and, specifically for MySQL, here.
I don't really instantiate an AndroidHttpClient anywhere in my code, but I do start a recognizer intent, which yields this exception at some point when my application runs:
Leak found
java.lang.IllegalStateException: AndroidHttpClient created and never closed
at android.net.http.AndroidHttpClient.<init>(AndroidHttpClient.java:152)
at android.net.http.AndroidHttpClient.newInstance(AndroidHttpClient.java:138)
at com.google.android.voicesearch.speechservice.SpeechServiceHttpClient.<init>(SpeechServiceHttpClient.java:59)
at com.google.android.voicesearch.speechservice.ServerConnectorImpl.<init>(ServerConnectorImpl.java:85)
at com.google.android.voicesearch.VoiceSearchContainerImpl.createRecognitionController(VoiceSearchContainerImpl.java:83)
at com.google.android.voicesearch.GoogleRecognitionService.onCreate(GoogleRecognitionService.java:65)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2066)
at android.app.ActivityThread.access$2500(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:993)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3835)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
at dalvik.system.NativeStart.main(Native Method)
Assuming the bug is not in Android's code but in mine, this leaked resource could have been created only in one of the following:
SpeechRecognizer.createSpeechRecognizer()
new RecognitionListener()
new Intent(SpeechRecognizer.RESULTS_RECOGNITION)
SpeechRecognizer.startListening(recognizerIntent)
But how do I know which one?
Assuming the bug is not in Android's code but in mine
The leak is in com.google.android.voicesearch, which is not your code.
If you can create a small sample project that demonstrates this leak, we can get an issue over to Google and hope that they will address it.
Why do you assume it's not in Android? SpeechRecognizer and RecognitionListener are in ASOP, so you can check (it's not there). Most probably SpeechServiceHttpClient uses an AndroidHttpClient internally. There is not much you can do but check you are calling all finalizer methods, if any (close(), shutdown(), etc), of the framework classes you are using.