рдбреНрд░рд╛рдЗрдВрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рд╕рд░рдлреЗрд╕ рд╡реНрдпреВ рдФрд░ рд╕реНрдХреНрд░реАрди-рдЖрдХрд╛рд░ рд╡рд╛рд▓реЗ рдмрд┐рдЯрдореИрдкреНрд╕ рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВ рдПрдХ рдХрд┐рддрд╛рдм рдореЗрдВ рдкреГрд╖реНрдареЛрдВ рдХреА рдПрдХ рдЪрд┐рдХрдиреА рдкреЗрдЬрд┐рдВрдЧ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ)ред
рдЙрдЪреНрдЪ рд╕реНрдХреНрд░реАрди рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди рд╡рд╛рд▓реЗ рдХрдИ рдЙрдкрдХрд░рдгреЛрдВ рдкрд░, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ
AndroidRuntime: java.lang.OutOfMemoryError: рдмрд┐рдЯрдореИрдк рдХрд╛ рдЖрдХрд╛рд░ VM рдмрдЬрдЯ рд╕реЗ рдЕрдзрд┐рдХ рд╣реИрд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдмрд┐рдЯрдореИрдк рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА, рд╕рд╛рде рд╣реА рд╕рд░реНрдлреЗрд╕ рд╡реНрдпреВ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣реАрдк рд╕реЗ рдЖрд░рдХреНрд╖рд┐рдд рд╣реИред рдвреЗрд░ рдХрд╛ рдЖрдХрд╛рд░ рд╕реАрдорд╛ рдЫреЛрдЯрд╛ рд╣реИ, рдЖрдорддреМрд░ рдкрд░ 10 рдПрдордмреА рд╕реЗ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХред рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдЕрд╕реЗрдВрдмрд▓ рдХрд░рддреЗ рд╕рдордп рдпрд╣ рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред
32 рдмрд┐рдЯреНрд╕ рд╕реЗ 16 рддрдХ рдкрд┐рдХреНрд╕реЗрд▓ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдХрдЯреМрддреА рдХрд░рдХреЗ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдЬреНрдпрд╛рджрд╛ рдорджрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рд╕рдорд╕реНрдпрд╛ рдмрд╛рдж рдореЗрдВ рд╕рд╛рдордиреЗ рдЖрддреА рд╣реИ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдЖрдк рд╕рд░рдлреЗрд╕ рд╡реНрдпреВ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдПрдХ рд╡рд┐рдВрдбреЛ рдЦреЛрд▓рддреЗ рд╣реИрдВ (рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ, рдпрд╣ рд╕реНрдХреНрд░реАрди рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдПрдХ рдФрд░ рдмрд┐рдЯрдореИрдк рдмрдирд╛рддрд╛ рд╣реИ)ред
рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдЧреНрд░рд╛рдлрд┐рдХ рдмрдлрд╝рд░реНрд╕ рдХрд╛ рдЖрдХрд╛рд░ 3-4 рд╕реНрдХреНрд░реАрди рддрдХ рд╕реАрдорд┐рдд рдХрд░рдирд╛ рдПрдХ рджреБрд░реНрднрд╛рдЧреНрдпрдкреВрд░реНрдг рдХрдо рд╣реИ! рдЖрдЗрдП рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрдиреНрдпрд╛рдп рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдмрд┐рдЯрдореИрдк рдХреА рдЕрдзрд┐рдХрд╛рдВрд╢ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рджреЗрд╢реА рдХреЛрдб (рдЬреЗрдПрдирдЖрдИ) рдореЗрдВ рд▓рд╛рдЧреВ рдХреА рдЬрд╛рддреА рд╣реИ, рдФрд░ рдмрдлрд░ рдХреЛ рдЬрд╛рд╡рд╛ рд╣реАрдк рдореЗрдВ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдПрдХ рдирд┐рдпрдорд┐рдд рд╢рд┐рд╢ рдореЙрд▓реЛрдХ рдХреА рдорджрдж рд╕реЗ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕ рдкрд░ рдвреЗрд░ рдЖрдХрд╛рд░ рдХреА рд╕реАрдорд╛рдПрдВ рдХреНрдпреЛрдВ рд▓рдЧрд╛рдИ рдЧрдИ рд╣реИрдВ?
рд╣рдо рд╕реНрд░реЛрдд рдХреЛрдб рдзреВрдореНрд░рдкрд╛рди рдХрд░рддреЗ рд╣реИрдВред
рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдмрд┐рдЯрдореИрдк рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдореЗрдореЛрд░реА рдЖрдмрдВрдЯрди dalvik.system.VMRuntime рдореЗрдВ trackExternalAllocation / trackExternalFree рддрд░реАрдХреЛрдВ рдХреА рдорджрдж рд╕реЗ рдкрдВрдЬреАрдХреГрдд рд╣реИред рдпрд╣ TrackExternalAllocation рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рд╕реАрдорд╛ рд╕реЗ рдЕрдзрд┐рдХ рд╕реНрдореГрддрд┐ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддрд╛ рд╣реИред
рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдЖрдк рдПрдХ рдмреЗрд╡рдХреВрдл рд░реЛрдмреЛрдЯ рдХреЛ рдзреЛрдЦрд╛ рджреЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ? рддрд╕реНрд╡реАрд░ рдХреЛ рд░рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдХрд╣реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдХреА рдЧрдИ рдмрд╛рд╣рд░реА рдореЗрдореЛрд░реА рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдореБрдХреНрдд рд╣реИред рдФрд░ рдЪрд┐рддреНрд░ рдЬрд╛рд░реА рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рдЕрдиреБрдХрд░рдг рдХрд░реЗрдВ рдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдореЗрдореЛрд░реА рдХрд╛ рдЖрдХрд╛рд░ рдмрд╕ рдХрдмреНрдЬрд╛ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдпрд╣ рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ - TrackExternalAllocation рдФрд░ trackExternalFree рддрд░реАрдХреЗ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ "рд╣реИрдХрд░" рддрд░реАрдХреЛрдВ рд╕реЗ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ - рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗред
рд╣рдо рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВред
рдПрдХ рд░рд┐рдХреНрдд Android рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдБред
рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, VMRuntime рдХреА рдкрд╣реБрдВрдЪ рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред
static class VMRuntimeHack { private Object runtime = null; private Method trackAllocation = null; private Method trackFree = null; public boolean trackAlloc(long size) { if (runtime == null) return false; try { Object res = trackAllocation.invoke(runtime, Long.valueOf(size)); return (res instanceof Boolean) ? (Boolean)res : true; } catch (IllegalArgumentException e) { return false; } catch (IllegalAccessException e) { return false; } catch (InvocationTargetException e) { return false; } } public boolean trackFree(long size) { if (runtime == null) return false; try { Object res = trackFree.invoke(runtime, Long.valueOf(size)); return (res instanceof Boolean) ? (Boolean)res : true; } catch (IllegalArgumentException e) { return false; } catch (IllegalAccessException e) { return false; } catch (InvocationTargetException e) { return false; } } public VMRuntimeHack() { boolean success = false; try { Class cl = Class.forName("dalvik.system.VMRuntime"); Method getRt = cl.getMethod("getRuntime", new Class[0]); runtime = getRt.invoke(null, new Object[0]); trackAllocation = cl.getMethod("trackExternalAllocation", new Class[] {long.class}); trackFree = cl.getMethod("trackExternalFree", new Class[] {long.class}); success = true; } catch (ClassNotFoundException e) { } catch (SecurityException e) { } catch (NoSuchMethodException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } if (!success) { Log.i(TAG, "VMRuntime hack does not work!"); runtime = null; trackAllocation = null; trackFree = null; } } } private static final VMRuntimeHack runtime = new VMRuntimeHack();
рд╣рдо рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ - рдХрд╛рд░рдЦрд╛рдиреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдмрд┐рдЯрдореИрдк рдмрдирд╛рдПрдВрдЧреЗ / рдЬрд╛рд░реА рдХрд░реЗрдВрдЧреЗред
рдпрд╣рд╛рдВ рд╣рдо рдпрд╛рдж рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдХрд┐рд╕ рдмрд┐рдЯрдореИрдк рдХреЗ рд▓рд┐рдП рд╣рдордиреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ рдореЗрдореЛрд░реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдареАрдХ рдХрд┐рдпрд╛ - рддрд╛рдХрд┐ рд░рд┐рд▓реАрдЬ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛ред
static class BitmapFactory { public BitmapFactory(boolean useHack) { this.useHack = useHack; }
рдЕрдм рд╣рдо рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВрдЧреЗ рдЬреЛ рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд╡рд┐рдзрд┐ рдХрд╛рдо рдХрд░рддреА рд╣реИред TestAllocation () рд╡рд┐рдзрд┐ рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рдЫрд╡рд┐рдпреЛрдВ рдХреА рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдЧреА (рдЬрдм рддрдХ рдХрд┐ OutOfMemory рдХреНрд░реИрд╢ рдпрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдорд╛ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛ рдЬрд╛рддреА)ред UseHack рдзреНрд╡рдЬ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╣реИрдХ рдХреЗ рд╕рд╛рде рдпрд╛ рдмрд┐рдирд╛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИред рд╡рд┐рдзрд┐ рдЙрд╕ рд░рд╛рд╢рд┐ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреА рд╣реИ рдЬреЛ рдЪрд┐рддреНрд░реЛрдВ рдХреЗ рддрд╣рдд рд▓реЗрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдереАред
public int testAllocation(boolean useHack, int maxAlloc) { System.gc(); BitmapFactory factory = new BitmapFactory(useHack); int allocated = 0;
рд╣рдо рд╣реИрдХ рдХреЗ рд╕рд╛рде рдФрд░ рдЗрд╕рдХреЗ рдмрд┐рдирд╛ - Activ.onCreate () рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХрд╣реЗрдВрдЧреЗред
рд╣рдо рд╕реНрдХреНрд░реАрди рдкрд░ рдФрд░ рд▓реЙрдЧ рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рджрд┐рдЦрд╛рдПрдВрдЧреЗред (рд▓реЗрдЖрдЙрдЯ "рдореБрдЦреНрдп" рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдЯреЗрдХреНрд╕реНрдЯ рд╡реНрдпреВ рдЖрдИрдбреА рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ, рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рд╣рдо рдкрд╛рда рдХреЛ рдмрджрд▓ рджреЗрдВрдЧреЗ)ред
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
рдЗрд╕рд▓рд┐рдП, рдкрд░рд┐рдгрд╛рдо рджреЗрдЦреЗрдВ рдФрд░ рджреЗрдЦреЗрдВ:
03-07 09:43:37.233: I/bmphack(17873): normally: 10 MB allocated
03-07 09:43:37.233: I/bmphack(17873): with hack: 48 MB allocated
рдПрдХ рд╣реИрдХ рдХреЗ рдмрд┐рдирд╛, рд╣рдо рдкреНрд░рддреНрдпреЗрдХ 1 рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рдХреА рд╕рд┐рд░реНрдл 10 рддрд╕реНрд╡реАрд░реЗрдВ рдмрдирд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗред рдПрдХ рд╣реИрдХ рдХреЗ рд╕рд╛рде - рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛ рдЬреЛ рд╣рдордиреЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреА (48 рдореЗрдЧрд╛рдмрд╛рдЗрдЯ)ред
рдмрдбрд╝реЗ рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде, рдкрд░реАрдХреНрд╖рдг рдЕрднреА рднреА рдореЗрд░реЗ рд╕рд┐рдореНрдпреБрд▓реЗрдЯрд░ рдкрд░ рд▓рдЯрдХрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ - ~ 58Mb рдХреЗ рдмрд╛рджред
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЛ рдпрд╣ рд▓реЗрдЦ рдорджрджрдЧрд╛рд░ рд▓рдЧреЗред