#include <math.h>
#include <stdio.h>
#include "com_example_conve_stroke_Conve_jni.h"
#include "com_example_conve_stroke_Conve_jni_EventListener.h"
#include "include/agg_basics.h"
#include "include/agg_rendering_buffer.h"
#include "include/agg_renderer_base.h"
#include "include/agg_renderer_scanline.h"
#include "include/agg_rasterizer_scanline_aa.h"
#include "include/agg_conv_stroke.h"
#include "include/agg_scanline_p.h"
#include "include/agg_path_storage.h"
#include "include/agg_vcgen_stroke.h"
#include "include/agg_vcgen_markers_term.h"
#include "include/agg_renderer_scanline.h"
#define AGG_RGB565
#include "include/pixel_formats.h"
typedef agg::renderer_base<pixfmt> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base>  solid_renderer;
using namespace agg;
typedef struct Color XColor;
struct Color
{
 int red;
 int green;
 int blue;
 //int pixel;
};
// Pallete
XColor pal[256];
// Global env ref (for callbacks)
static JavaVM *g_VM;
jclass jNativesCls;
jmethodID jSendImageMethod;
// Java image pixels: int ARGB
jintArray jImage;
int m_nWidth = 480;
int m_nHeight = 320;

void jni_send_pixels(int * data, int x, int y, int w, int h)
{
 JNIEnv *env;
 if ( !g_VM) {
  return ;
 }
 g_VM->AttachCurrentThread (&env, NULL);
 int iSize = 480 * 320;
 jImage = env-> NewIntArray(iSize);
 if (jSendImageMethod) {
  env->SetIntArrayRegion(jImage, 0, iSize, (jint *) data);
  // Call Java method
      env->CallStaticVoidMethod(jNativesCls , jSendImageMethod, jImage
   , (jint)x, (jint)y, (jint)w, (jint)h);
 }
}

void OnDraw()
{
 // 그리기위한 메모리 버퍼
 unsigned char     *m_pBuffer;
 rendering_buffer  *m_rdBuffer;
 ren_base    *m_rdBase;
 pixfmt     *m_pPixFmt;
 //
 m_pBuffer   = new unsigned char[m_nWidth * m_nHeight * 2];
 m_rdBuffer   = new rendering_buffer();
 m_rdBuffer->attach(m_pBuffer, m_nWidth, m_nHeight, m_nWidth * 2);
 m_pPixFmt   = new pixfmt(*m_rdBuffer);
 m_rdBase   = new ren_base(*m_pPixFmt);
 //
 m_rdBase->clear(rgba(1, 1, 1));
 rasterizer_scanline_aa<> ras;
 scanline_p8 sl;
 solid_renderer solid(*m_rdBase);
 path_storage path;
 path.move_to(50, 50);
 path.line_to(400, 150);
 path.line_to(50, 250);
 line_cap_e cap = butt_cap;
 line_join_e join = miter_join;
    // (1)
    conv_stroke<path_storage> stroke(path);
    stroke.line_join(join);
    stroke.line_cap(cap);
    stroke.miter_limit(4);
    stroke.width(20);
    ras.add_path(stroke);
    render_scanlines_aa_solid(ras, sl, *m_rdBase, rgba(0, 0, 0));
    // (1)
 int size = m_nWidth * m_nHeight;
  // ARGB pixels
 int pixels[size], i;
 unsigned char rgb[3];
 for ( i = 0 ; i < size ; i ++) {
  rgb[0] = m_pBuffer[i*2] & 0xF8; // r
  rgb[1] = (m_pBuffer[i*2] & 0x07) | ((m_pBuffer[i*2+1] & 0xE0) >> 3); // g
  rgb[2] = m_pBuffer[i*2+1] & 0x1F; // b
  pixels[i]  = 0xFF000000 | (rgb[2] << 16) | (rgb[1] << 8) | (rgb[0]);
 }
 jni_send_pixels(pixels,0,0, m_nWidth, m_nHeight);
}

int agg_main()
{
 JNIEnv *env;
 if ( !g_VM) {
  return 0;
 }
 g_VM->AttachCurrentThread (&env, NULL);
 // call OnInitGraphics(w, h);
 jmethodID mid = env->GetStaticMethodID(jNativesCls
   , "OnInitGraphics"  , "(II)V");
 if (mid) {env->CallStaticVoidMethod(jNativesCls , mid
       , m_nWidth, m_nHeight);
 }
 OnDraw();
 //g_pMD = new CDrawMD();
 //g_pMD->FireThread();
    return 1;
}
JNIEXPORT jint JNICALL Java_com_example_conve_1stroke_Conve_1jni_agg_1mainJNI
  (JNIEnv * env, jclass cls)
{
 env->GetJavaVM(&g_VM);
    jNativesCls = env->FindClass("com/example/conve_stroke/Conve_jni");
 if ( jNativesCls == 0 ) {
  printf("Unable to find class: com/example/conve_stroke/Conve_jni");
      return -1;
 }
 // Load doom.util.Natives.OnImageUpdate(char[])
 jSendImageMethod = env->GetStaticMethodID(jNativesCls
   , "OnImageUpdate"
   , "([IIIII)V");
 if ( jSendImageMethod == 0 ) {
  jni_printf("Unable to find method OnImageUpdate(byte[])");
     return -1;
 }
 return agg_main();
}


Wolf3D를 참고하여 만든 소스입니다.
그래픽은 agg를 사용했고 V자를 그립니다.
java쪽에서 jni를 호출하여 잘 그려지는 소스입니다.

근데 116번 라인을 117번,118번으로 바꾸고 OnDraw()함수도 CDrawMD클래스에 넣어서
쓰레드로  jni_send_pixels()함수를 호출하면 52번라인에서 Java method 를 호출하지 못합니다
JNI  WARNING :  0x4300000  is not  a  valid  JNI  reference  라고 뜨는데 인터넷에 뒤져보면

Local references and memory leaks

The automatic garbage collection of local references that are no longer in scope prevents memory leaks in most situations. This automatic garbage collection occurs when a native thread returns to Java (native methods) or detaches from the JVM (Invocation API). Local reference memory leaks are possible if automatic garbage collection does not occur. A memory leak might occur if a native method does not return to the JVM, or if a program that uses the Invocation API does not detach from the JVM.

Consider the code in the following example, where native code creates new local references in a loop:

while ( <condition> )
{
   jobject myObj = (*env)->NewObject( env, clz, mid, NULL );

   if ( NULL != myObj )
   {
      /* we know myObj is a valid local ref, so use it */
      jclass myClazz = (*env)->GetObjectClass(env, myObj);

      /* uses of myObj and myClazz, etc. but no new local refs */

      /* Without the following calls, we would leak */
      (*env)->DeleteLocalRef( env, myObj ); 
      (*env)->DeleteLocalRef( env, myClazz );
   }

} /* end while */

Although new local references overwrite the myObj and myClazz variables inside the loop, every local reference is kept in the root set. These references must be explicitly removed by the DeleteLocalRef call. Without the DeleteLocalRef calls, the local references are leaked until the thread returned to Java or detached from the JVM.

이것이 해결책 인것 같기도한데 해결이 안됩니다.


그리고 JNI_CreateJavaVM 이라고 있던데 이걸 사용 해야 되는건지 GetJavaVM 와는 어떻게 다른건지
아시는분 시원하게 답좀 해주세요.