java.lang.OutOfMemoryError: nicht zuzuordnen JNI Env
Als ich das erste mal laufen Async-task seine Arbeit gut. Tatsächlich kommt dieser Fehler unvorhersehbar. Ich Suche viele Lösungen zu diesem Thema, aber nichts funktioniert für mich.
Gemeinsame Lösung die ich habe ist, wir müssen schließen InputStream/ByteArrayInputStream & ich geschlossen, aber immer noch app wird Abstürzen.
Stacktrace:
java.lang.OutOfMemoryError: nicht zuzuordnen JNI Env an
java.lang.Thread.nativeCreate(Native Method) at
java.lang.Thread.start(Thread.java:730) an
java.util.gleichzeitige.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:941)
bei
java.util.gleichzeitige.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:1009)
bei
java.util.gleichzeitige.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1151)
bei
java.util.gleichzeitige.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
bei java.lang.Thread.run(Thread.java:761)
Folgenden ist AsyncTask;
public class AsyncHttpRequest extends AsyncTask<Void, Void, String> {
private String UrlString = "";
private boolean _showProgressDialog = false;
private CustomCircularLoadingDialog Dialog;
private Context mContext;
AppCompatActivity mActivity;
private IHttpRequestCompletedListener listener;
private boolean isActivity = true;
private String _messageText = "Please wait...";
private String type = "get";
private HttpUtility utility;
public AsyncHttpRequest(String urlString, Context context, IHttpRequestCompletedListener listener, boolean _showProgressDialog) {
UrlString = urlString;
this._showProgressDialog = _showProgressDialog;
this.mContext = context;
this.listener = listener;
Dialog = new CustomCircularLoadingDialog(this.mContext);
this.utility = new HttpUtility(this.UrlString, mContext);
Utilities.setCurrentHitURL(mContext, UrlString);
}
public void setOnCompletedListener(IHttpRequestCompletedListener listener) {
this.listener = listener;
}
public void setWaitMessage(String msgText) {
if (!msgText.equals(""))
msgText = "\n" + msgText;
this._messageText = _messageText + msgText;
}
public void addPostItem(NameValuePair nameValuePair) {
this.utility.addNameValuePairs(nameValuePair);
}
public void addGetHeader(String headerData) {
this.utility.addGetHeader(headerData);
}
public void addPostHeader(String headerData) {
this.utility.addPostHeader(headerData);
}
public void setTypePost() {
this.type = "post";
}
@Override
protected void onPreExecute() {
if (_showProgressDialog) {
Dialog.setMessage(this._messageText);
Dialog.setCancelable(false);
Dialog.setCanceledOnTouchOutside(false);
this.Dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
Dialog.show();
}
}
@Override
protected String doInBackground(Void... params) {
if (!Utilities.isNetworkAvailable(mContext))
return "No network available";
try {
if (this.type.equals("get"))
return utility.doGetRequest();
else
return utility.doPostRequest();
} catch (MediCorporateException tex) {
if (listener != null) {
if (isActivity) {
((Activity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
listener.OnHttpRequestError();
}
});
} else {
((GcmIntentService) mContext).runOnUIThread(new Runnable() {
@Override
public void run() {
listener.OnHttpRequestError();
}
});
}
}
Utilities.callCrashReport(mContext, tex);
}
Log.i("Exit ", "doInBackground");
return "";
}
@Override
protected void onPostExecute(String Result) {
if (_showProgressDialog)
this.Dialog.dismiss();
Log.i("Came in", "onPostExecute");
if (this.listener != null) {
if (!Utilities.isNullOrEmpty(Result))
listener.OnHttpRequestCompleted(Result);
else {
logoutUser();
listener.OnHttpRequestError();
}
}
Log.i("Exit ", "onPostExecute");
}
}
Folgenden sind die Funktionen zur Bearbeitung von Anfrage & Antworten in der HttpUtility-Klasse;
public String doGetRequest() throws MediCorporateException {
String resp = "";
int responseCode = 0;
try {
if (header != null) {
if (header.length() > 0) {
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Authorization", header);
}
}
responseCode = httpURLConnection.getResponseCode();
InputStream inputStream = new BufferedInputStream(this.httpURLConnection.getInputStream());
resp = readResponse(inputStream);
Log.v("Resp", "" + responseCode + " --- " + resp);
inputStream.close();
} catch (IOException ioExc) {
FileLog.e(getClass().getName(), ioExc);
resp = ioExc.getMessage();
throw new MediCorporateException("Http IO Exception...");
} catch (Exception ex) {
FileLog.e(getClass().getName(), ex);
throw new MediCorporateException("Http Error...");
} finally {
this.httpURLConnection.disconnect();
if (responseCode == 401)
return "" + responseCode;
if (responseCode != 200)
return null;
}
return resp;
}
Folgenden ist DoPostRequest() :
public String doGetRequest() throws MediCorporateException {
String resp = "";
int responseCode = 0;
try {
if (header != null) {
if (header.length() > 0) {
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Authorization", header);
}
}
responseCode = httpURLConnection.getResponseCode();
InputStream inputStream = new BufferedInputStream(this.httpURLConnection.getInputStream());
resp = readResponse(inputStream);
Log.v("Resp", "" + responseCode + " --- " + resp);
inputStream.close();
} catch (IOException ioExc) {
FileLog.e(getClass().getName(), ioExc);
resp = ioExc.getMessage();
throw new MediCorporateException("Http IO Exception...");
} catch (Exception ex) {
FileLog.e(getClass().getName(), ex);
throw new MediCorporateException("Http Error...");
} finally {
this.httpURLConnection.disconnect();
if (responseCode == 401)
return "" + responseCode;
if (responseCode != 200)
return null;
}
return resp;
}
folgenden ist zu Lesen & schreiben von response-Funktionen;
private void writePostMethod(OutputStream outputStream) throws Exception {
if (this.nameValuePairs.size() <= 0)
throw new Exception("Cannot use post method with no values to post");
String postStr = "";
for (NameValuePair item : this.nameValuePairs)
postStr += URLEncoder.encode(item.getName(), "UTF-8") + "=" + URLEncoder.encode(item.getValue(), "UTF-8") + "&";
postStr = postStr.substring(0, postStr.length() - 1);
Log.v("Post Values", postStr);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
writer.write(postStr);
writer.flush();
writer.close();
}
private String readResponse(InputStream inputStream) throws IOException {
int i;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
while ((i = inputStream.read()) != -1)
outputStream.write(i);
byte[] responseBytes = outputStream.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(responseBytes);
InputStreamReader reader;
if (!this._urlString.contains("token")) {
GZIPInputStream gzis = new GZIPInputStream(bais);
reader = new InputStreamReader(gzis);
gzis.close();
} else
reader = new InputStreamReader(bais);
BufferedReader in = new BufferedReader(reader);
StringBuilder total = new StringBuilder();
String readed;
while ((readed = in.readLine()) != null) {
total.append(readed);
bais.close();
}
in.close();
reader.close();
inputStream.close();
outputStream.close();
return total.toString();
}
- Wo ist der stacktrace?
- ich habe bearbeitet Sie meine Frage.
- Jeder thread kostet eine Menge in Bezug auf den Speicherverbrauch. Der OOM geschieht in einer nativen Methode, aber wenn die app ausgeschöpft hat, seine Haufen, der eigentliche Punkt, der OOM ist, ist irrelevant. Daher habe ich entfernt jni - tag.
- Siehe auch: stackoverflow.com/questions/24399294/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Scheint, wie Sie sind, nicht richtig schließen input/output-stream oder Puffer beim Lesen von Daten-stream. Versuchen Sie bitte das folgende snippet für das Lesen der Antwort von InputStream.
IOUtils verwenden der org.apache.Unterhaus.io. Sie können download jar
Obwohl die meisten von OOM sind aufgrund der heap-Größe zugeteilt, um die Anwendung. Wir können die Erhöhung der heap-Größe durch das hinzufügen von Tags in der manifest-Datei.
Nachdem Sie durch Ihre repo, ich habe herausgefunden, dass es für jede Ausnahme, die Sie versenden Protokolle und crash-Berichte auf FB. Das führt zu out of memory-in deinem Thread-Pool führt zu OOM. Bitte stellen Sie sicher, dass Sie senden, stürzt ab und events in batches.
Jeder thread kostet eine Menge in Bezug auf den Speicherverbrauch.
AsyncTask gelingt, seine thread-pool, aber es ist nicht optimiert für Netzwerk-Aktivität. Eigentlich, wenn Sie viele HTTP-Anfragen an den gleichen server, ist es besser, sowohl in Bezug auf Speicherverbrauch und Leistung insgesamt zu halten Sie auf dem gleichen thread, und die Wiederverwendung einer dauerhaften Verbindung, Wann immer möglich. AsyncTask ist nicht der Ansicht, solche Fragen.
Es gibt durchaus ein paar zuverlässige HTTP-clients stellen async-requests, z.B. OkHttp oder volley, oder Android Asynchronous Http Client von J. Smith und viele andere Projekte auf GitHub.
Es ist OK zu erfinden, Ihre eigenen HTTP-client, aber es wäre zumindest klug, um zu studieren, was andere getan haben, in diesem Bereich, und welche Fehler Sie gemacht vor.