2013-06-10 2 views
0

서버에서 요청을 받고 업데이트를받는 C 스레드가 있습니다. 업데이트는 JNI 호출을 통해 Java로 전송됩니다. 내 문제는 최대 100 개의 항목 (서버에서 100 개의 응답,이 부분을 수정할 수 없음)을 포함 할 수있는 플레이어의 인벤토리를 수신 할 때 발생합니다. 때로는 문제가 발생하지만 때때로 재고가 많을수록 문제가 더 자주 발생합니다.C 스레드에서 업데이트하면 안무가가 프레임을 건너 뛰게됩니다.

나는 다음과 같은 메시지를 제외하고는 로그 캣에서 예외를 얻을하지 않습니다

06-10 10:09:46.085: I/Choreographer(23815): Skipped 87 frames! The application may be doing too much work on its main thread. 

그리고는 내 응용 프로그램을 닫습니다. runOnUiThread으로 UI를 업데이트하는 행을 주석으로 추가한다고해도 앱 크래시가 발생한다고도 말할 필요가 있습니다.

JNI에서 Java로 돌아갈 때 UI 스레드에 있는지 확인하려고했지만 Looper.myLooper() == Looper.getMainLooper() 반환 false입니다.

누구나 같은 문제가 발생 했습니까? C 쓰레드가 메인 쓰레드와 관련이있다? 감사합니다

편집

나는 다음과 같은 호출이 만들어진 서버에서 업데이트가 나타납니다 자바 스레드 (안 UI 스레드)에서

  • : notifyAll
  • 라는 이름의 C 함수를 호출을
  • notifyAllupdate이라는 C 함수를 호출합니다.이 함수는 Java에서 해당 함수를 호출합니다 (아래 코드 참조).

    ,451,515,
    void UpdateListenerWrapper::update(Update& u) { 
        // Retrieve the current JNIEnv* with the cached JVM 
        int status; 
        JNIEnv* env; 
        bool isAttached = false; 
    
        status = gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2); 
        if(status < 0) { 
         __android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to get JNI environment"); 
         status = gCachedJVM->AttachCurrentThread(&env, NULL); 
         if(status < 0) { 
          __android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to attach current thread"); 
          return; 
         } 
         isAttached = true; 
        } 
    
        jmethodID update = env->GetMethodID(gClazzUpdateListenerWrapper, "update", "(J)V"); // J stands for Java long type 
    
        // Call Java method update from jUpdateListener object 
        env->CallVoidMethod(jUpdateListener, update, (jlong)(intptr_t)&u); // Pointer as agument, we'll build the Update object in Java 
    
        if (isAttached) { 
         gCachedJVM->DetachCurrentThread(); 
        } 
    } 
    

나는 문제가 UI 스레드에 대한 포인터를 반환 GETENV 어쩌면이 줄 gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2);에 있고 생각합니다. 그것이 문제일까요? 이 문제를 어떻게 해결할 수 있습니까?

답변

0

내 문제에 대한 해결책을 찾았지만 내 앱과 관련이 있습니다. update 함수 (Java 측)에서 이 있었는데 break이 없었으며 각 업데이트가 UI 스레드가 아닌 새 네트워크 호출을 트리거했습니다. 불쾌한 당신의 시간과 당신의 대답을 찾아 주셔서 감사합니다, 당신은 나를 해결하는 데 도움이 :

1

앱 충돌은 Choreographer 불만과 관련이 없습니다. 이것들은 애니메이션이 굶어 죽었 음을 나타내는 경고 일뿐입니다.

정말로 logcat 출력을 스레드 ID를 표시하는 모드로보고 싶습니다. 명령 줄에서 adb logcat -v threadtime을 사용하는 것이 좋습니다. 서버 상호 작용 시작시 로그 메시지를 넣으면 UI 스레드에서 실행 중인지 쉽게 알 수 있습니다 (스레드 ID와 프로세스 ID는 동일합니다. 시스템에서는 보장되지 않지만 앱에서는 신뢰할 수 있습니다).

메인 스레드에서 네트워크 또는 데이터베이스 I/O를 실행하지 마십시오. 시간이 너무 오래 걸리면 시스템이 지겨워지고 앱이 응답하지 않는다고 결정합니다.

JNI를 통해 원시 코드를 호출해도 다른 스레드로 전환되지 않습니다. C 쓰레드와 Java 쓰레드는 없다. C 쓰레드와 Java 쓰여진 코드를 호출 할 수있다.

제목 : Re : 질문 업데이트 ...

GetEnv는 항상 현재 스레드에 대한 데이터에 대한 포인터를 반환합니다. 또한 CallVoidMethod은 항상 현재 스레드에서 발생합니다. JNIEnv을 잘못 전달했다고하더라도 스레드를 "점프"하지는 않습니다.

많은 메소드가있는 클래스에서는 GetMethodID 호출이 비쌀 수 있으므로 gClassUpdateListenerWrapper이 설정된 지점에서 캐시를 시도해야합니다. VM에서 스레드를 연결하거나 분리하는 것은 비용이 많이들 수 있으며 가장 피해야 할 사항입니다. Java 메서드에서 호출하는 경우 정의에 따라 스레드가 이미 연결되어 있습니다. 나는 isAttached이 결코 설정되지 않는다고 생각합니다.

실제로 안무가가 왜 굶주리고 있는지 설명하지 않습니다. 난 아직도 update() 로그 메시지를 추가하고 어떤 스레드에서 무슨 일이 일어나고 있는지 감각을 얻으려면 logcat -v threadtime을 사용하고 traceview 시간이 가고 있는지 볼 필요가 있다고 생각합니다.

+0

답해 주셔서 감사합니다. 실제로 나는 나의 문제가 어디서 왔는지를 발견했다. 그러나 나는 그것을 어떻게 풀어야할지 모른다. 내 업데이트보기 – Fr4nz

+0

업데이트 된 답변을 주셔서 감사합니다. 그 말에 전리품을 드리겠습니다. – Fr4nz

+0

그래서 먼저 메소드 ID를 캐싱하려고했지만 이전과 같은 결과가있었습니다. 나는'logcat -v threadtime'을 사용하려고했는데 메인 스레드에서 실행되지 않았기 때문에이 로그를'06-13 17 : 25 : 38.505 6252 6762 E UpdateListenerWrapper :: update1'라고합니다. 그 후 traceview (http://stackoverflow.com/a/14872118/1304830)를 사용하려고했지만 동시에 업데이트와 녹음을 요청할 때 내 앱이 즉시 중단되기 시작했습니다. – Fr4nz