我有一个递归方法,查找给定String
中字符的所有可能的组合。递归方法适用于包含9个字母或更少的任何String
。它在4秒左右完成9个字母的递归方法。但是,一旦有超过9个字母就会遇到问题。该方法运行大约2分钟,有大量的GC行写入日志,当过程最终完成时,我得到一个Throwing OutOfMemoryError
异常。是否有超过9个字母的字符串要求太多?这全部在AsyncTask
上完成。递归字符串的排列无法完成超过9个字符 - 抛出OutOfMemoryError
这里是堆栈跟踪:
07-29 12:24:39.335 17389-17389/com.example.test.apptest W/art: Throwing OutOfMemoryError "Failed to allocate a 76 byte allocation with 4194304 free bytes and 12MB until OOM; failed due to fragmentation (required continguous free 4096 bytes for a new buffer where largest contiguous free 0 bytes)" (recursive case)
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: "main" prio=5 tid=1 Runnable
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: | group="main" sCount=0 dsCount=0 obj=0x73e1e258 self=0xb40f4500
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: | sysTid=17389 nice=0 cgrp=default sched=0/0 handle=0xb77e1c00
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: | state=R schedstat=(0 0 0) utm=899 stm=114 core=1 HZ=100
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: | stack=0xbf326000-0xbf328000 stackSize=8MB
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: | held mutexes= "mutator lock"(shared held)
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: native: #00 pc 0058bd02 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::ArtMethod*, void*)+226)
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: native: #01 pc 0055285e /system/lib/libart.so (art::Thread::ThrowOutOfMemoryError(char const*)+542)
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: native: #02 pc 0029b6cd /system/lib/libart.so (art::gc::Heap::ThrowOutOfMemoryError(art::Thread*, unsigned int, art::gc::AllocatorType)+1559)
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: native: #03 pc 002a4a62 /system/lib/libart.so (art::gc::Heap::AllocateInternalWithGc(art::Thread*, art::gc::AllocatorType, unsigned int, unsigned int*, unsigned int*, unsigned int*, art::mirror::Class**)+5218)
07-29 12:24:39.344 17389-17389/com.example.test.apptest W/art: native: #04 pc 001ade47 /system/lib/libart.so (art::mirror::PrimitiveArray<int>::Alloc(art::Thread*, unsigned int)+2423)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: native: #05 pc 0054dd6e /system/lib/libart.so (_jobject* art::Thread::CreateInternalStackTrace<false>(art::ScopedObjectAccessAlreadyRunnable const&) const+298)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: native: #06 pc 0047fc31 /system/lib/libart.so (art::Throwable_nativeFillInStackTrace(_JNIEnv*, _jclass*)+52)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: native: #07 pc 0002475e /data/dalvik-cache/x86/[email protected]@boot.oat (Java_java_lang_Throwable_nativeFillInStackTrace__+98)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.Throwable.nativeFillInStackTrace!(Native method)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.Throwable.fillInStackTrace(Throwable.java:166)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.Throwable.<init>(Throwable.java:95)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.Error.<init>(Error.java:48)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.VirtualMachineError.<init>(VirtualMachineError.java:46)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.OutOfMemoryError.<init>(OutOfMemoryError.java:44)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:146)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.StringBuilder.append(StringBuilder.java:216)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at com.android.internal.os.RuntimeInit.Clog_e(RuntimeInit.java:61)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at com.android.internal.os.RuntimeInit.-wrap0(RuntimeInit.java:-1)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:94)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
07-29 12:24:39.345 17389-17389/com.example.test.apptest W/art: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
07-29 12:24:39.346 17389-17389/com.example.test.apptest I/Process: Sending signal. PID: 17389 SIG: 9
和递归方法:
//Initial permutation method
public void permutation(String lettersToCombine) {
permutation("", lettersToCombine);
}
//Recursion method to find all combinations of letters in a given string.
private void permutation(String prefix, String passedLetters) {
//Set int to the size of the String passed.
int lengthOfPassedLetters = passedLetters.length();
//Add the prefix to the ArrayList.
if (lengthOfPassedLetters == 0) myList.add(prefix);
//Loop through this the amount of times of the size of passed letters.
for (int i = 0; i < lengthOfPassedLetters; i++) {
/*Call this same method every time the loop is entered. Setting prefix to the character at position of i
prefix is passed into the method for first argument. For the second argument another String is passed containing
the second argument made up of the letters already processed and the letters left too.
*/
permutation(prefix + passedLetters.charAt(i), passedLetters.substring(0, i) + passedLetters.substring(i + 1,
lengthOfPassedLetters));
}
已更新的答案。 –