我的用户收到了很多OutOfMemoryError报告,每个报告都来自同一个Activity,其中包含MapView。我认为这是一个孤立的异常,仅在我的应用程序中只有一个位置,而且我无法弄清楚问题出在哪里。谁能给我一些指示为什么会这样吗?
我已针对此问题删除了一些不需要的代码,因此如果有人认为问题可能在于此,我将其发布。
堆栈痕迹
Stack Trace #1
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:677)
at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
at com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
at com.google.android.maps.MapView$2.onScaleBegin(MapView.java:371)
at android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
at com.google.android.maps.MapView.onTouchEvent(MapView.java:646)
at android.view.View.dispatchTouchEvent(View.java:3778)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:959)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1716)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1124)
at android.app.Activity.dispatchTouchEvent(Activity.java:2125)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1700)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1822)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
Stack Trace #2
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:151)
at com.google.android.maps.ZoomHelper.doZoom(ZoomHelper.java:140)
at com.google.android.maps.MapView.doZoom(MapView.java:1478)
at com.google.android.maps.MapView.doZoom(MapView.java:1487)
at com.google.android.maps.MapController.zoomOut(MapController.java:439)
at com.hookedroid.fishingcompanion.GoogleMaps$3.onClick(GoogleMaps.java:133)
at android.view.View.performClick(View.java:2405)
at android.view.View$PerformClick.run(View.java:8813)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Stack Trace #3
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:346)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:372)
at com.hookedroid.fishingcompanion.maps.CrosshairOverlay.draw(CrosshairOverlay.java:32)
at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:45)
at com.google.android.maps.MapView.onDraw(MapView.java:494)
at android.view.View.draw(View.java:6742)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1913)
at android.view.ViewRoot.draw(ViewRoot.java:1407)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4646)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
活动
public class GoogleMaps extends MapActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.googlemaps_layout);
intent = getIntent();
currentMode = intent.getIntExtra("MAP_MODE", 0);
initControls();
initMembers();
currentOverlayMode = prefs.getInt("map_viewmode", 0);
populateMap();
}
private void initMembers() {
mDbHelper = new FishingCompanionDB(this);
mDbHelper.open();
catchList = new ArrayList<FishEntry>();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefsEditor = prefs.edit();
}
private void initControls() {
mMaps = (MapView)findViewById(R.id.google_maps);
mMaps.setClickable(true);
mMaps.setLongClickable(true);
mapController = mMaps.getController();
mOverlayModeBtn = (Button)findViewById(R.id.googlemaps_overlay_btn);
mOverlayModeBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (currentOverlayMode < 1)
currentOverlayMode++;
else
currentOverlayMode = 0;
switch (currentOverlayMode) {
case OVERLAY_STREET:
mMaps.setSatellite(false);
mMaps.setStreetView(true);
prefsEditor.putInt("map_viewmode", OVERLAY_STREET);
break;
case OVERLAY_SAT:
mMaps.setStreetView(false);
mMaps.setSatellite(true);
prefsEditor.putInt("map_viewmode", OVERLAY_SAT);
break;
}
prefsEditor.commit();
mMaps.invalidate();
}
});
mZoomInBtn = (Button)findViewById(R.id.googlemaps_btn_zoomin);
mZoomInBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mapController.zoomIn();
}
});
mZoomOutBtn = (Button)findViewById(R.id.googlemaps_btn_zoomout);
mZoomOutBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mapController.zoomOut();
}
});
}
private void populateMap() {
overlays = mMaps.getOverlays();
overlays.clear();
overlays.add(new CrosshairOverlay(this, R.drawable.mapcenter));
mSelectPos = (Button)findViewById(R.id.googlemaps_select_location);
mSelectPos.setVisibility(View.VISIBLE);
mSelectPos.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
GeoPoint centerGp = mMaps.getMapCenter();
double lat = centerGp.getLatitudeE6()/1E6;
double lng = centerGp.getLongitudeE6()/1E6;
Intent i;
if (currentMode == SELECT_POS_WEATHER) {
i = new Intent(GoogleMaps.this, WeatherLookup.class);
i.putExtra("WEATHER_LAT", lat);
i.putExtra("WEATHER_LNG", lng);
}
else {
i = new Intent(GoogleMaps.this, AddLocation.class);
i.putExtra("LOCATION_LAT", lat);
i.putExtra("LOCATION_LNG", lng);
}
i.putExtra("MODE", 1);
startActivity(i);
finish();
}
});
mMaps.invalidate();
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
十字线叠加
public class CrosshairOverlay extends Overlay {
private Context mContext;
private int resourceId;
public CrosshairOverlay(Context context, int resId) {
this.mContext = context;
this.resourceId = resId;
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
super.draw(canvas, mapView, shadow);
GeoPoint centerGp = mapView.getMapCenter();
Projection projection = mapView.getProjection();
Point centerPoint = projection.toPixels(centerGp, null);
Paint p = new Paint();
Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), resourceId);
canvas.drawBitmap(bmp, (centerPoint.x - (bmp.getWidth()/2)), (centerPoint.y - (bmp.getHeight()/2)), p);
return true;
}
}
DUMPSYS MEMINFO
** MEMINFO in pid 25493 [com.hookedroid.fishingcompanion] **
native dalvik other total
size: 10036 7495 N/A 17531
allocated: 9955 3965 N/A 13920
free: 80 3530 N/A 3610
(Pss): 3717 1480 6703 11900
(shared dirty): 668 1512 8056 10236
(priv dirty): 3696 804 5024 9524
Objects
Views: 0 ViewRoots: 0
AppContexts: 0 Activities: 0
Assets: 3 AssetManagers: 3
Local Binders: 19 Proxy Binders: 21
Death Recipients: 1
OpenSSL Sockets: 0
SQL
heap: 527 MEMORY_USED: 527
PAGECACHE_OVERFLOW: 62 MALLOC_SIZE: 50
DATABASES
pgsz dbsz Lookaside(b) Dbname
1 16 260 FishingCompanion
1 18 63 google_analytics.db
我下载了该应用程序并在通过dumpsys观察内存的同时进行了操作。
情况看起来很正常,每次都会回收内存。我无法重现这种情况,但是我确实看到一个可能与之相关的峰值。每当您在地图上四处移动或在卫星中缩放(基本刷新图块)时,内存中都会出现短暂的峰值。如果您执行得足够快,则不会给它回收的机会,它会上升。
现在,我的手机是Android
3.3.4,并且配置良好,因此GC可能效率更高。我不知道我的旧测试电话是否会较慢地回收内存,因此,当我到达地图时(例如,添加鱼后),我是否仍会保留以前未被GC回收的活动中的内存。然后,我要做的就是去我的位置并通过放大/缩小来检查内容。加上以前的活动中的先前记忆,可能会使手机达到极限。
不过,这只是一个理论,我在旅途中,无法使用我所有的测试电话。您知道崩溃的手机版本吗?我会在3-4天后回来,我可以在旧手机上尝试该应用。
更新: 我已经在这个应用程序上进行了更多的实验。我几乎可以肯定,连续添加鱼会增加更多的回忆。我一直在添加和删除鱼,并通过dumpsys
meminfo检查内存是否持续增加。专业版的真正用户,甚至是不断添加和删除鱼的精简版用户,最终可能会接近极限并随后进入地图,这将触发内存不足错误,因为内存会进入地图。这是我几次添加和删除鱼后的快照
** pid 11572中的MEMINFO [com.hookedroid.fishingcompanion.lite] **
dalvik本机其他总数限制位图nativeBmp
大小:19728 18251不适用37979 32768不适用
已分配:17174 14674 N / A 31848 N / A 3144 0
免费:405 3577 N / A 3982 N / AN / AN / A
(PSS):12750 1771 25944 40465 N / AN / AN / A
(脏共享):908 1544 5800 8252 N / AN / AN / A
(私人肮脏):12732 1008 24208 37948 N / AN / AN / A
您的私有内存总数达到37,948,如果我继续添加和删除鱼,我敢肯定,它将最终抛出OutOfMemoryException
更多更新(几分钟后): 我使用上述理论使应用程序崩溃。在发生之前,我必须多次添加和移除鱼。该应用程序崩溃之前可能超过50条鱼。
我的猜测是SQL无法正确清理。在每组添加和删除10条鱼(这是lite版本的限制)之后查看一下dumpsys,我看到
的SQL
堆:6581 MEMORY_USED:6581
PAGECACHE_OVERFLOW:173 MALLOC_SIZE:50
资料库
pgsz dbsz Lookaside(b)Dbname
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 33钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
1 16 62钓鱼伴侣
即使我已经删除了鱼,SQL内存仍在增加。如果我继续这样做一段时间,最终它将达到手机的上限,并且转到地图(这会导致内存中的跳转)将触发内存不足异常,似乎表明地图页面是原因,而我认为添加/删除鱼页面是真正原因的一部分(我说“真正原因的一部分”,因为我不知道是否会发生类似的影响,例如我是否添加新位置)。
当总内存约为58MB时,我得到了正确的OutMemoryException(这可能因手机而异)。作为参考,这是我得到的一个类似的OutOfMemoryException:
D / dalvikvm(11572):GC_FOR_MALLOC释放了125K,11%释放了25734K / 28743K,外部4047K / 4695K,暂停了188ms
D / AndroidRuntime(11572):关闭VM
W / dalvikvm(11572):threadid = 1:线程以未捕获的异常退出(group = 0x4001d648)
E / AndroidRuntime(11572):致命异常:主要
E / AndroidRuntime(11572):java.lang.OutOfMemoryError:位图大小超出VM预算(堆大小= 28743KB,已分配= 25734KB,位图大小= 4047KB)
E / AndroidRuntime(11572):位于android.graphics.Bitmap.nativeCreate(本机方法)
E / AndroidRuntime(11572):位于android.graphics.Bitmap.createBitmap(Bitmap.java:695)
E / AndroidRuntime(11572):位于com.google.android.maps.ZoomHelper.createSnapshot(ZoomHelper.java:444)
E / AndroidRuntime(11572):位于com.google.android.maps.ZoomHelper.beginZoom(ZoomHelper.java:194)
E / AndroidRuntime(11572):位于com.google.android.maps.MapView $ 2.onScaleBegin(MapView.java:380)
E / AndroidRuntime(11572):位于android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:216)
E / AndroidRuntime(11572):位于com.google.android.maps.MapView.onTouchEvent(MapView.java:682)
E / AndroidRuntime(11572):位于android.view.View.dispatchTouchEvent(View.java:3932)
E / AndroidRuntime(11572):位于android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:955)
E / AndroidRuntime(11572):位于android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
E / AndroidRuntime(11572):位于android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
E / AndroidRuntime(11572):位于android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1015)
希望能帮助到你
编辑: 我正在使用热切加载,我认为这将影响它的工作方式。
我有一个类处理一个图像,这可能是一个缓慢的过程。当工作完成时,该类包含图像的一些特性,如主色。 我有许多其他的代码想知道主颜色,当他们要求它时,它可能是或可能没有准备好。 我还没有找到使用RXJava2实现这一点的简单方法。有人能帮帮我吗? null ReplaySubject似乎有一些我正在寻找的属性,但我不确定如何正确地实现它。
例如: 如果父div具有类为“not_available”的内部div,则需要隐藏“快速订购”按钮 尝试了一些JavaScript: 另一个JavaScript示例: 但是它或者根本不起作用,或者对所有具有class.quckorder-btn的div都起作用。只需要在一个div中运行函数,该div中没有一个div具有类“not_available” 请求任何帮助。谢谢
我正在尝试从技能作业表中删除一行 以下是我的疑问 但它抛出以下错误; 致命错误:未捕获的异常'异常'消息'您有一个错误在您的SQL语法;检查手册,对应于您的MySQL服务器版本的正确的语法使用附近'skj内连接作业j上<--plhd--0/<--#############################################################################
Camel in Action的结尾是在时使用
问题内容: 我正在编写此android应用程序,其中有许多扩展Activity类的活动。我还需要一个使用MapView在屏幕上同时显示Map和ListView的活动(类似于在地图上使用图钉显示房屋的出租房屋清单)。由于我有一个扩展Activity类的基类,因此其他活动扩展了该基类。只有具有地图的特定屏幕才需要扩展MapActivity类。当我尝试这样做时,我抛出了IllegalAccessErro