#vulnerable code 
                                boolean checkPlatform(Platform platform, String[] defaultNames) {
        if (platform == null) {
            return true;
        }
        if (defaultNames == null) {
            defaultNames = new String[0];
        }
        String platform2 = properties.getProperty("platform");
        String[][] names = { platform.value().length > 0 ? platform.value() : defaultNames, platform.not() };
        boolean[] matches = { false, false };
        for (int i = 0; i < names.length; i++) {
            for (String s : names[i]) {
                if (platform2.startsWith(s)) {
                    matches[i] = true;
                    break;
                }
            }
        }
        if ((names[0].length == 0 || matches[0]) && (names[1].length == 0 || !matches[1])) {
            return true;
        }
        return false;
    } 
                            #location 13 
                            #vulnerability type NULL_DEREFERENCE
#fixed code
                                boolean classes(boolean handleExceptions, boolean defineAdapters, boolean convertStrings,
            String loadSuffix, String baseLoadSuffix, String classPath, Class<?> ... classes) {
        String version = Generator.class.getPackage().getImplementationVersion();
        if (version == null) {
            version = "unknown";
        }
        String warning = "// Generated by JavaCPP version " + version + ": DO NOT EDIT THIS FILE";
        out.println(warning);
        out.println();
        if (out2 != null) {
            out2.println(warning);
            out2.println();
        }
        ClassProperties clsProperties = Loader.loadProperties(classes, properties, true);
        for (String s : clsProperties.get("platform.pragma")) {
            out.println("#pragma " + s);
        }
        for (String s : clsProperties.get("platform.define")) {
            out.println("#define " + s);
        }
        out.println();
        out.println("#ifdef _WIN32");
        out.println("    #define _JAVASOFT_JNI_MD_H_");
        out.println();
        out.println("    #define JNIEXPORT __declspec(dllexport)");
        out.println("    #define JNIIMPORT __declspec(dllimport)");
        out.println("    #define JNICALL __stdcall");
        out.println();
        out.println("    typedef int jint;");
        out.println("    typedef long long jlong;");
        out.println("    typedef signed char jbyte;");
        out.println("#elif defined(__GNUC__) && !defined(__ANDROID__)");
        out.println("    #define _JAVASOFT_JNI_MD_H_");
        out.println();
        out.println("    #define JNIEXPORT __attribute__((visibility(\"default\")))");
        out.println("    #define JNIIMPORT");
        out.println("    #define JNICALL");
        out.println();
        out.println("    typedef int jint;");
        out.println("    typedef long long jlong;");
        out.println("    typedef signed char jbyte;");
        out.println("#endif");
        out.println();
        out.println("#include <jni.h>");
        if (out2 != null) {
            out2.println("#include <jni.h>");
        }
        out.println();
        out.println("#ifdef __ANDROID__");
        out.println("    #include <android/log.h>");
        out.println("#elif defined(__APPLE__) && defined(__OBJC__)");
        out.println("    #include <TargetConditionals.h>");
        out.println("    #include <Foundation/Foundation.h>");
        out.println("#endif");
        out.println();
        out.println("#ifdef __linux__");
        out.println("    #include <malloc.h>");
        out.println("    #include <sys/types.h>");
        out.println("    #include <sys/stat.h>");
        out.println("    #include <sys/sysinfo.h>");
        out.println("    #include <fcntl.h>");
        out.println("    #include <unistd.h>");
        out.println("    #include <dlfcn.h>");
        out.println("#elif defined(__APPLE__)");
        out.println("    #include <sys/types.h>");
        out.println("    #include <sys/sysctl.h>");
        out.println("    #include <mach/mach_init.h>");
        out.println("    #include <mach/mach_host.h>");
        out.println("    #include <mach/task.h>");
        out.println("    #include <unistd.h>");
        out.println("    #include <dlfcn.h>");
        out.println("#elif defined(_WIN32)");
        out.println("    #define NOMINMAX");
        out.println("    #include <windows.h>");
        out.println("    #include <psapi.h>");
        out.println("#endif");
        out.println();
        out.println("#if defined(__ANDROID__) || TARGET_OS_IPHONE");
        out.println("    #define NewWeakGlobalRef(obj) NewGlobalRef(obj)");
        out.println("    #define DeleteWeakGlobalRef(obj) DeleteGlobalRef(obj)");
        out.println("#endif");
        out.println();
        out.println("#include <limits.h>");
        out.println("#include <stddef.h>");
        out.println("#ifndef _WIN32");
        out.println("    #include <stdint.h>");
        out.println("#endif");
        out.println("#include <stdio.h>");
        out.println("#include <stdlib.h>");
        out.println("#include <string.h>");
        out.println("#include <exception>");
        out.println("#include <memory>");
        out.println("#include <new>");
        if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) {
            out.println();
            out.println("#if defined(NATIVE_ALLOCATOR) && defined(NATIVE_DEALLOCATOR)");
            out.println("    void* operator new(std::size_t size, const std::nothrow_t&) throw() {");
            out.println("        return NATIVE_ALLOCATOR(size);");
            out.println("    }");
            out.println("    void* operator new[](std::size_t size, const std::nothrow_t&) throw() {");
            out.println("        return NATIVE_ALLOCATOR(size);");
            out.println("    }");
            out.println("    void* operator new(std::size_t size) throw(std::bad_alloc) {");
            out.println("        return NATIVE_ALLOCATOR(size);");
            out.println("    }");
            out.println("    void* operator new[](std::size_t size) throw(std::bad_alloc) {");
            out.println("        return NATIVE_ALLOCATOR(size);");
            out.println("    }");
            out.println("    void operator delete(void* ptr) throw() {");
            out.println("        NATIVE_DEALLOCATOR(ptr);");
            out.println("    }");
            out.println("    void operator delete[](void* ptr) throw() {");
            out.println("        NATIVE_DEALLOCATOR(ptr);");
            out.println("    }");
            out.println("#endif");
        }
        out.println();
        out.println("#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))");
        out.println("#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))");
        out.println();
        out.println("#if defined(_MSC_VER)");
        out.println("    #define JavaCPP_noinline __declspec(noinline)");
        out.println("    #define JavaCPP_hidden /* hidden by default */");
        out.println("#elif defined(__GNUC__)");
        out.println("    #define JavaCPP_noinline __attribute__((noinline)) __attribute__ ((unused))");
        out.println("    #define JavaCPP_hidden   __attribute__((visibility(\"hidden\"))) __attribute__ ((unused))");
        out.println("#else");
        out.println("    #define JavaCPP_noinline");
        out.println("    #define JavaCPP_hidden");
        out.println("#endif");
        out.println();

        if (loadSuffix == null) {
            loadSuffix = "";
            String p = clsProperties.getProperty("platform.library.static", "false").toLowerCase();
            if (p.equals("true") || p.equals("t") || p.equals("")) {
                loadSuffix = "_" + clsProperties.getProperty("platform.library");
            }
        }

        if (classes != null) {
            List exclude = clsProperties.get("platform.exclude");
            List[] include = { clsProperties.get("platform.include"),
                               clsProperties.get("platform.cinclude") };
            for (int i = 0; i < include.length; i++) {
                if (include[i] != null && include[i].size() > 0) {
                    if (i == 1) {
                        out.println("extern \"C\" {");
                        if (out2 != null) {
                            out2.println("#ifdef __cplusplus");
                            out2.println("extern \"C\" {");
                            out2.println("#endif");
                        }
                    }
                    for (String s : (List<String>)include[i]) {
                        if (exclude.contains(s)) {
                            continue;
                        }
                        String line = "#include ";
                        if (!s.startsWith("<") && !s.startsWith("\"")) {
                            line += '"';
                        }
                        line += s;
                        if (!s.endsWith(">") && !s.endsWith("\"")) {
                            line += '"';
                        }
                        out.println(line);
                        if (out2 != null) {
                            out2.println(line);
                        }
                    }
                    if (i == 1) {
                        out.println("}");
                        if (out2 != null) {
                            out2.println("#ifdef __cplusplus");
                            out2.println("}");
                            out2.println("#endif");
                        }
                    }
                    out.println();
                }
            }
        }
        out.println("static JavaVM* JavaCPP_vm = NULL;");
        out.println("static bool JavaCPP_haveAllocObject = false;");
        out.println("static bool JavaCPP_haveNonvirtual = false;");
        out.println("static const char* JavaCPP_classNames[" + jclasses.size() + "] = {");
        Iterator<Class> classIterator = jclasses.iterator();
        int maxMemberSize = 0;
        while (classIterator.hasNext()) {
            Class c = classIterator.next();
            out.print("        \"" + c.getName().replace('.','/') + "\"");
            if (classIterator.hasNext()) {
                out.println(",");
            }
            Set<String> m = members.get(c);
            if (m != null && m.size() > maxMemberSize) {
                maxMemberSize = m.size();
            }
        }
        out.println(" };");
        out.println("static jclass JavaCPP_classes[" + jclasses.size() + "] = { NULL };");
        out.println("static jfieldID JavaCPP_addressFID = NULL;");
        out.println("static jfieldID JavaCPP_positionFID = NULL;");
        out.println("static jfieldID JavaCPP_limitFID = NULL;");
        out.println("static jfieldID JavaCPP_capacityFID = NULL;");
        out.println("static jfieldID JavaCPP_deallocatorFID = NULL;");
        out.println("static jfieldID JavaCPP_ownerAddressFID = NULL;");
        out.println("static jmethodID JavaCPP_initMID = NULL;");
        out.println("static jmethodID JavaCPP_arrayMID = NULL;");
        out.println("static jmethodID JavaCPP_stringMID = NULL;");
        out.println("static jmethodID JavaCPP_getBytesMID = NULL;");
        out.println("static jmethodID JavaCPP_toStringMID = NULL;");
        out.println();
        out.println("static inline void JavaCPP_log(const char* fmt, ...) {");
        out.println("    va_list ap;");
        out.println("    va_start(ap, fmt);");
        out.println("#ifdef __ANDROID__");
        out.println("    __android_log_vprint(ANDROID_LOG_ERROR, \"javacpp\", fmt, ap);");
        out.println("#elif defined(__APPLE__) && defined(__OBJC__)");
        out.println("    NSLogv([NSString stringWithUTF8String:fmt], ap);");
        out.println("#else");
        out.println("    vfprintf(stderr, fmt, ap);");
        out.println("    fprintf(stderr, \"\\n\");");
        out.println("#endif");
        out.println("    va_end(ap);");
        out.println("}");
        out.println();
        if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) {
            out.println("static inline jboolean JavaCPP_trimMemory() {");
            out.println("#if defined(__linux__) && !defined(__ANDROID__)");
            out.println("    return (jboolean)malloc_trim(0);");
            out.println("#else");
            out.println("    return 0;");
            out.println("#endif");
            out.println("}");
            out.println();
            out.println("static inline jlong JavaCPP_physicalBytes() {");
            out.println("    jlong size = 0;");
            out.println("#ifdef __linux__");
            out.println("    static int fd = open(\"/proc/self/statm\", O_RDONLY, 0);");
            out.println("    if (fd >= 0) {");
            out.println("        char line[256];");
            out.println("        char* s;");
            out.println("        int n;");
            out.println("        lseek(fd, 0, SEEK_SET);");
            out.println("        if ((n = read(fd, line, sizeof(line))) > 0 && (s = (char*)memchr(line, ' ', n)) != NULL) {");
            out.println("            size = (jlong)(atoll(s + 1) * getpagesize());");
            out.println("        }");
            out.println("        // no close(fd);");
            out.println("    }");
            out.println("#elif defined(__APPLE__)");
            out.println("    task_basic_info info;");
            out.println("    mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;");
            out.println("    if (task_info(current_task(), TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS) {");
            out.println("        size = (jlong)info.resident_size;");
            out.println("    }");
            out.println("#elif defined(_WIN32)");
            out.println("    PROCESS_MEMORY_COUNTERS counters;");
            out.println("    if (GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters))) {");
            out.println("        size = (jlong)counters.WorkingSetSize;");
            out.println("    }");
            out.println("#endif");
            out.println("    return size;");
            out.println("}");
            out.println();
            out.println("static inline jlong JavaCPP_totalPhysicalBytes() {");
            out.println("    jlong size = 0;");
            out.println("#ifdef __linux__");
            out.println("    struct sysinfo info;");
            out.println("    if (sysinfo(&info) == 0) {");
            out.println("        size = info.totalram;");
            out.println("    }");
            out.println("#elif defined(__APPLE__)");
            out.println("    size_t length = sizeof(size);");
            out.println("    sysctlbyname(\"hw.memsize\", &size, &length, NULL, 0);");
            out.println("#elif defined(_WIN32)");
            out.println("    MEMORYSTATUSEX status;");
            out.println("    status.dwLength = sizeof(status);");
            out.println("    if (GlobalMemoryStatusEx(&status)) {");
            out.println("        size = status.ullTotalPhys;");
            out.println("    }");
            out.println("#endif");
            out.println("    return size;");
            out.println("}");
            out.println();
            out.println("static inline jlong JavaCPP_availablePhysicalBytes() {");
            out.println("    jlong size = 0;");
            out.println("#ifdef __linux__");
            out.println("    int fd = open(\"/proc/meminfo\", O_RDONLY, 0);");
            out.println("    if (fd >= 0) {");
            out.println("        char temp[4096];");
            out.println("        char *s;");
            out.println("        int n;");
            out.println("        if ((n = read(fd, temp, sizeof(temp))) > 0 && (s = (char*)memmem(temp, n, \"MemAvailable:\", 13)) != NULL) {");
            out.println("            size = (jlong)(atoll(s + 13) * 1024);");
            out.println("        }");
            out.println("        close(fd);");
            out.println("    }");
            out.println("    if (size == 0) {");
            out.println("        struct sysinfo info;");
            out.println("        if (sysinfo(&info) == 0) {");
            out.println("            size = info.freeram;");
            out.println("        }");
            out.println("    }");
            out.println("#elif defined(__APPLE__)");
            out.println("    vm_statistics_data_t info;");
            out.println("    mach_msg_type_number_t count = HOST_VM_INFO_COUNT;");
            out.println("    if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&info, &count) == KERN_SUCCESS) {");
            out.println("        size = (jlong)info.free_count * getpagesize();");
            out.println("    }");
            out.println("#elif defined(_WIN32)");
            out.println("    MEMORYSTATUSEX status;");
            out.println("    status.dwLength = sizeof(status);");
            out.println("    if (GlobalMemoryStatusEx(&status)) {");
            out.println("        size = status.ullAvailPhys;");
            out.println("    }");
            out.println("#endif");
            out.println("    return size;");
            out.println("}");
            out.println();
            out.println("static inline jint JavaCPP_totalProcessors() {");
            out.println("    jint total = 0;");
            out.println("#ifdef __linux__");
            out.println("    total = sysconf(_SC_NPROCESSORS_CONF);");
            out.println("#elif defined(__APPLE__)");
            out.println("    size_t length = sizeof(total);");
            out.println("    sysctlbyname(\"hw.logicalcpu_max\", &total, &length, NULL, 0);");
            out.println("#elif defined(_WIN32)");
            out.println("    SYSTEM_INFO info;");
            out.println("    GetSystemInfo(&info);");
            out.println("    total = info.dwNumberOfProcessors;");
            out.println("#endif");
            out.println("    return total;");
            out.println("}");
            out.println();
            out.println("static inline jint JavaCPP_totalCores() {");
            out.println("    jint total = 0;");
            out.println("#ifdef __linux__");
            out.println("    const int n = sysconf(_SC_NPROCESSORS_CONF);");
            out.println("    int pids[n], cids[n];");
            out.println("    for (int i = 0; i < n; i++) {");
            out.println("        int fd = 0, pid = 0, cid = 0;");
            out.println("        char temp[256];");
            out.println("        sprintf(temp, \"/sys/devices/system/cpu/cpu%d/topology/physical_package_id\", i);");
            out.println("        if ((fd = open(temp, O_RDONLY, 0)) >= 0) {");
            out.println("            if (read(fd, temp, sizeof(temp)) > 0) {");
            out.println("                pid = atoi(temp);");
            out.println("            }");
            out.println("            close(fd);");
            out.println("        }");
            out.println("        sprintf(temp, \"/sys/devices/system/cpu/cpu%d/topology/core_id\", i);");
            out.println("        if ((fd = open(temp, O_RDONLY, 0)) >= 0) {");
            out.println("            if (read(fd, temp, sizeof(temp)) > 0) {");
            out.println("                cid = atoi(temp);");
            out.println("            }");
            out.println("            close(fd);");
            out.println("        }");
            out.println("        bool found = false;");
            out.println("        for (int j = 0; j < total; j++) {");
            out.println("            if (pids[j] == pid && cids[j] == cid) {");
            out.println("                found = true;");
            out.println("                break;");
            out.println("            }");
            out.println("        }");
            out.println("        if (!found) {");
            out.println("            pids[total] = pid;");
            out.println("            cids[total] = cid;");
            out.println("            total++;");
            out.println("        }");
            out.println("    }");
            out.println("#elif defined(__APPLE__)");
            out.println("    size_t length = sizeof(total);");
            out.println("    sysctlbyname(\"hw.physicalcpu_max\", &total, &length, NULL, 0);");
            out.println("#elif defined(_WIN32)");
            out.println("    SYSTEM_LOGICAL_PROCESSOR_INFORMATION *info = NULL;");
            out.println("    DWORD length = 0;");
            out.println("    BOOL success = GetLogicalProcessorInformation(info, &length);");
            out.println("    while (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {");
            out.println("        info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)realloc(info, length);");
            out.println("        success = GetLogicalProcessorInformation(info, &length);");
            out.println("    }");
            out.println("    if (success && info != NULL) {");
            out.println("        length /= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);");
            out.println("        for (DWORD i = 0; i < length; i++) {");
            out.println("            if (info[i].Relationship == RelationProcessorCore) {");
            out.println("                total++;");
            out.println("            }");
            out.println("        }");
            out.println("    }");
            out.println("    free(info);");
            out.println("#endif");
            out.println("    return total;");
            out.println("}");
            out.println();
            out.println("static inline jint JavaCPP_totalChips() {");
            out.println("    jint total = 0;");
            out.println("#ifdef __linux__");
            out.println("    const int n = sysconf(_SC_NPROCESSORS_CONF);");
            out.println("    int pids[n];");
            out.println("    for (int i = 0; i < n; i++) {");
            out.println("        int fd = 0, pid = 0;");
            out.println("        char temp[256];");
            out.println("        sprintf(temp, \"/sys/devices/system/cpu/cpu%d/topology/physical_package_id\", i);");
            out.println("        if ((fd = open(temp, O_RDONLY, 0)) >= 0) {");
            out.println("            if (read(fd, temp, sizeof(temp)) > 0) {");
            out.println("                pid = atoi(temp);");
            out.println("            }");
            out.println("            close(fd);");
            out.println("        }");
            out.println("        bool found = false;");
            out.println("        for (int j = 0; j < total; j++) {");
            out.println("            if (pids[j] == pid) {");
            out.println("                found = true;");
            out.println("                break;");
            out.println("            }");
            out.println("        }");
            out.println("        if (!found) {");
            out.println("            pids[total] = pid;");
            out.println("            total++;");
            out.println("        }");
            out.println("    }");
            out.println("#elif defined(__APPLE__)");
            out.println("    size_t length = sizeof(total);");
            out.println("    sysctlbyname(\"hw.packages\", &total, &length, NULL, 0);");
            out.println("#elif defined(_WIN32)");
            out.println("    SYSTEM_LOGICAL_PROCESSOR_INFORMATION *info = NULL;");
            out.println("    DWORD length = 0;");
            out.println("    BOOL success = GetLogicalProcessorInformation(info, &length);");
            out.println("    while (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {");
            out.println("        info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)realloc(info, length);");
            out.println("        success = GetLogicalProcessorInformation(info, &length);");
            out.println("    }");
            out.println("    if (success && info != NULL) {");
            out.println("        length /= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);");
            out.println("        for (DWORD i = 0; i < length; i++) {");
            out.println("            if (info[i].Relationship == RelationProcessorPackage) {");
            out.println("                total++;");
            out.println("            }");
            out.println("        }");
            out.println("    }");
            out.println("    free(info);");
            out.println("#endif");
            out.println("    return total;");
            out.println("}");
            out.println();
            out.println("static inline void* JavaCPP_addressof(const char* name) {");
            out.println("    void *address = NULL;");
            out.println("#if defined(__linux__) || defined(__APPLE__)");
            out.println("    address = dlsym(RTLD_DEFAULT, name);");
            out.println("#elif defined(_WIN32)");
            out.println("    HANDLE process = GetCurrentProcess();");
            out.println("    HMODULE *modules = NULL;");
            out.println("    DWORD length = 0, needed = 0;");
            out.println("    BOOL success = EnumProcessModules(process, modules, length, &needed);");
            out.println("    while (success && needed > length) {");
            out.println("        modules = (HMODULE*)realloc(modules, length = needed);");
            out.println("        success = EnumProcessModules(process, modules, length, &needed);");
            out.println("    }");
            out.println("    if (success && modules != NULL) {");
            out.println("        length = needed / sizeof(HMODULE);");
            out.println("        for (DWORD i = 0; i < length; i++) {");
            out.println("            address = (void*)GetProcAddress(modules[i], name);");
            out.println("            if (address != NULL) {");
            out.println("                break;");
            out.println("            }");
            out.println("        }");
            out.println("    }");
            out.println("    free(modules);");
            out.println("#endif");
            out.println("    return address;");
            out.println("}");
            out.println();
        }
        out.println("static JavaCPP_noinline jclass JavaCPP_getClass(JNIEnv* env, int i) {");
        out.println("    if (JavaCPP_classes[i] == NULL && env->PushLocalFrame(1) == 0) {");
        out.println("        jclass cls = env->FindClass(JavaCPP_classNames[i]);");
        out.println("        if (cls == NULL || env->ExceptionCheck()) {");
        out.println("            JavaCPP_log(\"Error loading class %s.\", JavaCPP_classNames[i]);");
        out.println("            return NULL;");
        out.println("        }");
        out.println("        JavaCPP_classes[i] = (jclass)env->NewWeakGlobalRef(cls);");
        out.println("        if (JavaCPP_classes[i] == NULL || env->ExceptionCheck()) {");
        out.println("            JavaCPP_log(\"Error creating global reference of class %s.\", JavaCPP_classNames[i]);");
        out.println("            return NULL;");
        out.println("        }");
        out.println("        env->PopLocalFrame(NULL);");
        out.println("    }");
        out.println("    return JavaCPP_classes[i];");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jfieldID JavaCPP_getFieldID(JNIEnv* env, int i, const char* name, const char* sig) {");
        out.println("    jclass cls = JavaCPP_getClass(env, i);");
        out.println("    if (cls == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    jfieldID fid = env->GetFieldID(cls, name, sig);");
        out.println("    if (fid == NULL || env->ExceptionCheck()) {");
        out.println("        JavaCPP_log(\"Error getting field ID of %s/%s\", JavaCPP_classNames[i], name);");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return fid;");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jmethodID JavaCPP_getMethodID(JNIEnv* env, int i, const char* name, const char* sig) {");
        out.println("    jclass cls = JavaCPP_getClass(env, i);");
        out.println("    if (cls == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    jmethodID mid = env->GetMethodID(cls, name, sig);");
        out.println("    if (mid == NULL || env->ExceptionCheck()) {");
        out.println("        JavaCPP_log(\"Error getting method ID of %s/%s\", JavaCPP_classNames[i], name);");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return mid;");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jmethodID JavaCPP_getStaticMethodID(JNIEnv* env, int i, const char* name, const char* sig) {");
        out.println("    jclass cls = JavaCPP_getClass(env, i);");
        out.println("    if (cls == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    jmethodID mid = env->GetStaticMethodID(cls, name, sig);");
        out.println("    if (mid == NULL || env->ExceptionCheck()) {");
        out.println("        JavaCPP_log(\"Error getting static method ID of %s/%s\", JavaCPP_classNames[i], name);");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    return mid;");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline jobject JavaCPP_createPointer(JNIEnv* env, int i, jclass cls = NULL) {");
        out.println("    if (cls == NULL && (cls = JavaCPP_getClass(env, i)) == NULL) {");
        out.println("        return NULL;");
        out.println("    }");
        out.println("    if (JavaCPP_haveAllocObject) {");
        out.println("        return env->AllocObject(cls);");
        out.println("    } else {");
        out.println("        jmethodID mid = env->GetMethodID(cls, \"<init>\", \"(Lorg/bytedeco/javacpp/Pointer;)V\");");
        out.println("        if (mid == NULL || env->ExceptionCheck()) {");
        out.println("            JavaCPP_log(\"Error getting Pointer constructor of %s, while VM does not support AllocObject()\", JavaCPP_classNames[i]);");
        out.println("            return NULL;");
        out.println("        }");
        out.println("        return env->NewObject(cls, mid, NULL);");
        out.println("    }");
        out.println("}");
        out.println();
        out.println("static JavaCPP_noinline void JavaCPP_initPointer(JNIEnv* env, jobject obj, const void* ptr, jlong size, void* owner, void (*deallocator)(void*)) {");
        out.println("    if (deallocator != NULL) {");
        out.println("        jvalue args[4];");
        out.println("        args[0].j = ptr_to_jlong(ptr);");
        out.println("        args[1].j = size;");
        out.println("        args[2].j = ptr_to_jlong(owner);");
        out.println("        args[3].j = ptr_to_jlong(deallocator);");
        out.println("        if (JavaCPP_haveNonvirtual) {");
        out.println("            env->CallNonvirtualVoidMethodA(obj, JavaCPP_getClass(env, "
                                     + jclasses.index(Pointer.class) + "), JavaCPP_initMID, args);");
        out.println("        } else {");
        out.println("            env->CallVoidMethodA(obj, JavaCPP_initMID, args);");
        out.println("        }");
        out.println("    } else {");
        out.println("        env->SetLongField(obj, JavaCPP_addressFID, ptr_to_jlong(ptr));");
        out.println("        env->SetLongField(obj, JavaCPP_limitFID, (jlong)size);");
        out.println("        env->SetLongField(obj, JavaCPP_capacityFID, (jlong)size);");
        out.println("    }");
        out.println("}");
        out.println();
        if (handleExceptions || convertStrings) {
            out.println("static JavaCPP_noinline jstring JavaCPP_createString(JNIEnv* env, const char* ptr) {");
            out.println("    if (ptr == NULL) {");
            out.println("        return NULL;");
            out.println("    }");
            out.println("#ifdef MODIFIED_UTF8_STRING");
            out.println("    return env->NewStringUTF(ptr);");
            out.println("#else");
            out.println("    size_t length = strlen(ptr);");
            out.println("    jbyteArray bytes = env->NewByteArray(length < INT_MAX ? length : INT_MAX);");
            out.println("    env->SetByteArrayRegion(bytes, 0, length < INT_MAX ? length : INT_MAX, (signed char*)ptr);");
            out.println("    return (jstring)env->NewObject(JavaCPP_getClass(env, " + jclasses.index(String.class) + "), JavaCPP_stringMID, bytes);");
            out.println("#endif");
            out.println("}");
            out.println();
        }
        if (convertStrings) {
            out.println("static JavaCPP_noinline const char* JavaCPP_getStringBytes(JNIEnv* env, jstring str) {");
            out.println("    if (str == NULL) {");
            out.println("        return NULL;");
            out.println("    }");
            out.println("#ifdef MODIFIED_UTF8_STRING");
            out.println("    return env->GetStringUTFChars(str, NULL);");
            out.println("#else");
            out.println("    jbyteArray bytes = (jbyteArray)env->CallObjectMethod(str, JavaCPP_getBytesMID);");
            out.println("    if (bytes == NULL || env->ExceptionCheck()) {");
            out.println("        JavaCPP_log(\"Error getting bytes from string.\");");
            out.println("        return NULL;");
            out.println("    }");
            out.println("    jsize length = env->GetArrayLength(bytes);");
            out.println("    signed char* ptr = new (std::nothrow) signed char[length + 1];");
            out.println("    if (ptr != NULL) {");
            out.println("        env->GetByteArrayRegion(bytes, 0, length, ptr);");
            out.println("        ptr[length] = 0;");
            out.println("    }");
            out.println("    return (const char*)ptr;");
            out.println("#endif");
            out.println("}");
            out.println();
            out.println("static JavaCPP_noinline void JavaCPP_releaseStringBytes(JNIEnv* env, jstring str, const char* ptr) {");
            out.println("#ifdef MODIFIED_UTF8_STRING");
            out.println("    if (str != NULL) {");
            out.println("        env->ReleaseStringUTFChars(str, ptr);");
            out.println("    }");
            out.println("#else");
            out.println("    delete[] ptr;");
            out.println("#endif");
            out.println("}");
            out.println();
        }
        out.println("class JavaCPP_hidden JavaCPP_exception : public std::exception {");
        out.println("public:");
        out.println("    JavaCPP_exception(const char* str) throw() {");
        out.println("        if (str == NULL) {");
        out.println("            strcpy(msg, \"Unknown exception.\");");
        out.println("        } else {");
        out.println("            strncpy(msg, str, sizeof(msg));");
        out.println("            msg[sizeof(msg) - 1] = 0;");
        out.println("        }");
        out.println("    }");
        out.println("    virtual const char* what() const throw() { return msg; }");
        out.println("    char msg[1024];");
        out.println("};");
        out.println();
        if (handleExceptions) {
            out.println("#ifndef GENERIC_EXCEPTION_CLASS");
            out.println("#define GENERIC_EXCEPTION_CLASS std::exception");
            out.println("#endif");
            out.println("static JavaCPP_noinline jthrowable JavaCPP_handleException(JNIEnv* env, int i) {");
            out.println("    jstring str = NULL;");
            out.println("    try {");
            out.println("        throw;");
            out.println("    } catch (GENERIC_EXCEPTION_CLASS& e) {");
            out.println("        str = JavaCPP_createString(env, e.what());");
            out.println("    } catch (...) {");
            out.println("        str = JavaCPP_createString(env, \"Unknown exception.\");");
            out.println("    }");
            out.println("    jmethodID mid = JavaCPP_getMethodID(env, i, \"<init>\", \"(Ljava/lang/String;)V\");");
            out.println("    if (mid == NULL) {");
            out.println("        return NULL;");
            out.println("    }");
            out.println("    return (jthrowable)env->NewObject(JavaCPP_getClass(env, i), mid, str);");
            out.println("}");
            out.println();
        }
        Class deallocator, nativeDeallocator;
        try {
            deallocator = Class.forName(Pointer.class.getName() + "$Deallocator", false, Pointer.class.getClassLoader());
            nativeDeallocator = Class.forName(Pointer.class.getName() + "$NativeDeallocator", false, Pointer.class.getClassLoader());
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(ex);
        }
        if (defineAdapters) {
            out.println("static JavaCPP_noinline void* JavaCPP_getPointerOwner(JNIEnv* env, jobject obj) {");
            out.println("    if (obj != NULL) {");
            out.println("        jobject deallocator = env->GetObjectField(obj, JavaCPP_deallocatorFID);");
            out.println("        if (deallocator != NULL && env->IsInstanceOf(deallocator, JavaCPP_getClass(env, "
                                                                + jclasses.index(nativeDeallocator) + "))) {");
            out.println("            return jlong_to_ptr(env->GetLongField(deallocator, JavaCPP_ownerAddressFID));");
            out.println("        }");
            out.println("    }");
            out.println("    return NULL;");
            out.println("}");
            out.println();
            out.println("#include <vector>");
            out.println("template<typename P, typename T = P> class JavaCPP_hidden VectorAdapter {");
            out.println("public:");
            out.println("    VectorAdapter(const P* ptr, typename std::vector<T>::size_type size, void* owner) : ptr((P*)ptr), size(size), owner(owner),");
            out.println("        vec2(ptr ? std::vector<T>((P*)ptr, (P*)ptr + size) : std::vector<T>()), vec(vec2) { }");
            out.println("    VectorAdapter(const std::vector<T>& vec) : ptr(0), size(0), owner(0), vec2(vec), vec(vec2) { }");
            out.println("    VectorAdapter(      std::vector<T>& vec) : ptr(0), size(0), owner(0), vec(vec) { }");
            out.println("    VectorAdapter(const std::vector<T>* vec) : ptr(0), size(0), owner(0), vec(*(std::vector<T>*)vec) { }");
            out.println("    void assign(P* ptr, typename std::vector<T>::size_type size, void* owner) {");
            out.println("        this->ptr = ptr;");
            out.println("        this->size = size;");
            out.println("        this->owner = owner;");
            out.println("        vec.assign(ptr, ptr + size);");
            out.println("    }");
            out.println("    static void deallocate(void* owner) { operator delete(owner); }");
            out.println("    operator P*() {");
            out.println("        if (vec.size() > size) {");
            out.println("            ptr = (P*)(operator new(sizeof(P) * vec.size(), std::nothrow_t()));");
            out.println("        }");
            out.println("        if (ptr) {");
            out.println("            std::copy(vec.begin(), vec.end(), ptr);");
            out.println("        }");
            out.println("        size = vec.size();");
            out.println("        owner = ptr;");
            out.println("        return ptr;");
            out.println("    }");
            out.println("    operator const P*()        { return &vec[0]; }");
            out.println("    operator std::vector<T>&() { return vec; }");
            out.println("    operator std::vector<T>*() { return ptr ? &vec : 0; }");
            out.println("    P* ptr;");
            out.println("    typename std::vector<T>::size_type size;");
            out.println("    void* owner;");
            out.println("    std::vector<T> vec2;");
            out.println("    std::vector<T>& vec;");
            out.println("};");
            out.println();
            out.println("#include <string>");
            out.println("class JavaCPP_hidden StringAdapter {");
            out.println("public:");
            out.println("    StringAdapter(const          char* ptr, size_t size, void* owner) : ptr((char*)ptr), size(size), owner(owner),");
            out.println("        str2(ptr ? (char*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }");
            out.println("    StringAdapter(const signed   char* ptr, size_t size, void* owner) : ptr((char*)ptr), size(size), owner(owner),");
            out.println("        str2(ptr ? (char*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }");
            out.println("    StringAdapter(const unsigned char* ptr, size_t size, void* owner) : ptr((char*)ptr), size(size), owner(owner),");
            out.println("        str2(ptr ? (char*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }");
            out.println("    StringAdapter(const std::string& str) : ptr(0), size(0), owner(0), str2(str), str(str2) { }");
            out.println("    StringAdapter(      std::string& str) : ptr(0), size(0), owner(0), str(str) { }");
            out.println("    StringAdapter(const std::string* str) : ptr(0), size(0), owner(0), str(*(std::string*)str) { }");
            out.println("    void assign(char* ptr, size_t size, void* owner) {");
            out.println("        this->ptr = ptr;");
            out.println("        this->size = size;");
            out.println("        this->owner = owner;");
            out.println("        str.assign(ptr ? ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0);");
            out.println("    }");
            out.println("    void assign(const          char* ptr, size_t size, void* owner) { assign((char*)ptr, size, owner); }");
            out.println("    void assign(const signed   char* ptr, size_t size, void* owner) { assign((char*)ptr, size, owner); }");
            out.println("    void assign(const unsigned char* ptr, size_t size, void* owner) { assign((char*)ptr, size, owner); }");
            out.println("    static void deallocate(void* owner) { delete[] (char*)owner; }");
            out.println("    operator char*() {");
            out.println("        const char* data = str.data();");
            out.println("        if (str.size() > size) {");
            out.println("            ptr = new (std::nothrow) char[str.size()+1];");
            out.println("            if (ptr) memset(ptr, 0, str.size()+1);");
            out.println("        }");
            out.println("        if (ptr && memcmp(ptr, data, str.size()) != 0) {");
            out.println("            memcpy(ptr, data, str.size());");
            out.println("            if (size > str.size()) ptr[str.size()] = 0;");
            out.println("        }");
            out.println("        size = str.size();");
            out.println("        owner = ptr;");
            out.println("        return ptr;");
            out.println("    }");
            out.println("    operator       signed   char*() { return (signed   char*)(operator char*)(); }");
            out.println("    operator       unsigned char*() { return (unsigned char*)(operator char*)(); }");
            out.println("    operator const          char*() { return                 str.c_str(); }");
            out.println("    operator const signed   char*() { return (signed   char*)str.c_str(); }");
            out.println("    operator const unsigned char*() { return (unsigned char*)str.c_str(); }");
            out.println("    operator         std::string&() { return str; }");
            out.println("    operator         std::string*() { return ptr ? &str : 0; }");
            out.println("    char* ptr;");
            out.println("    size_t size;");
            out.println("    void* owner;");
            out.println("    std::string str2;");
            out.println("    std::string& str;");
            out.println("};");
            out.println();
            out.println("#ifdef SHARED_PTR_NAMESPACE");
            out.println("template<class T> class SharedPtrAdapter {");
            out.println("public:");
            out.println("    typedef SHARED_PTR_NAMESPACE::shared_ptr<T> S;");
            out.println("    SharedPtrAdapter(const T* ptr, size_t size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
            out.println("            sharedPtr2(owner != NULL && owner != ptr ? *(S*)owner : S((T*)ptr)), sharedPtr(sharedPtr2) { }");
            out.println("    SharedPtrAdapter(const S& sharedPtr) : ptr(0), size(0), owner(0), sharedPtr2(sharedPtr), sharedPtr(sharedPtr2) { }");
            out.println("    SharedPtrAdapter(      S& sharedPtr) : ptr(0), size(0), owner(0), sharedPtr(sharedPtr) { }");
            out.println("    SharedPtrAdapter(const S* sharedPtr) : ptr(0), size(0), owner(0), sharedPtr(*(S*)sharedPtr) { }");
            out.println("    void assign(T* ptr, size_t size, S* owner) {");
            out.println("        this->ptr = ptr;");
            out.println("        this->size = size;");
            out.println("        this->owner = owner;");
            out.println("        this->sharedPtr = owner != NULL && owner != ptr ? *(S*)owner : S((T*)ptr);");
            out.println("    }");
            out.println("    static void deallocate(void* owner) { delete (S*)owner; }");
            out.println("    operator typename SHARED_PTR_NAMESPACE::remove_const<T>::type*() {");
            out.println("        ptr = sharedPtr.get();");
            out.println("        if (owner == NULL || owner == ptr) {");
            out.println("            owner = new S(sharedPtr);");
            out.println("        }");
            out.println("        return ptr;");
            out.println("    }");
            out.println("    operator const T*() { return sharedPtr.get(); }");
            out.println("    operator       S&() { return sharedPtr; }");
            out.println("    operator       S*() { return &sharedPtr; }");
            out.println("    T* ptr;");
            out.println("    size_t size;");
            out.println("    void* owner;");
            out.println("    S sharedPtr2;");
            out.println("    S& sharedPtr;");
            out.println("};");
            out.println("#endif");
            out.println();
            out.println("#ifdef UNIQUE_PTR_NAMESPACE");
            out.println("template<class T> class UniquePtrAdapter {");
            out.println("public:");
            out.println("    typedef UNIQUE_PTR_NAMESPACE::unique_ptr<T> U;");
            out.println("    UniquePtrAdapter(const T* ptr, size_t size, void* owner) : ptr((T*)ptr), size(size), owner(owner),");
            out.println("            uniquePtr2(owner != NULL && owner != ptr ? U() : U((T*)ptr)),");
            out.println("            uniquePtr(owner != NULL && owner != ptr ? *(U*)owner : uniquePtr2) { }");
            out.println("    UniquePtrAdapter(const U& uniquePtr) : ptr(0), size(0), owner(0), uniquePtr((U&)uniquePtr) { }");
            out.println("    UniquePtrAdapter(      U& uniquePtr) : ptr(0), size(0), owner(0), uniquePtr(uniquePtr) { }");
            out.println("    UniquePtrAdapter(const U* uniquePtr) : ptr(0), size(0), owner(0), uniquePtr(*(U*)uniquePtr) { }");
            out.println("    void assign(T* ptr, size_t size, U* owner) {");
            out.println("        this->ptr = ptr;");
            out.println("        this->size = size;");
            out.println("        this->owner = owner;");
            out.println("        this->uniquePtr = owner != NULL && owner != ptr ? *(U*)owner : U((T*)ptr);");
            out.println("    }");
            out.println("    static void deallocate(void* owner) { delete (U*)owner; }");
            out.println("    operator typename UNIQUE_PTR_NAMESPACE::remove_const<T>::type*() {");
            out.println("        ptr = uniquePtr.get();");
            out.println("        if (owner == NULL || owner == ptr) {");
            out.println("            owner = new U(UNIQUE_PTR_NAMESPACE::move(uniquePtr));");
            out.println("        }");
            out.println("        return ptr;");
            out.println("    }");
            out.println("    operator const T*() { return uniquePtr.get(); }");
            out.println("    operator       U&() { return uniquePtr; }");
            out.println("    operator       U*() { return &uniquePtr; }");
            out.println("    T* ptr;");
            out.println("    size_t size;");
            out.println("    void* owner;");
            out.println("    U uniquePtr2;");
            out.println("    U& uniquePtr;");
            out.println("};");
            out.println("#endif");
            out.println();
        }
        if (!functions.isEmpty() || !virtualFunctions.isEmpty()) {
            out.println("static JavaCPP_noinline void JavaCPP_detach(bool detach) {");
            out.println("#ifndef NO_JNI_DETACH_THREAD");
            out.println("    if (detach && JavaCPP_vm->DetachCurrentThread() != JNI_OK) {");
            out.println("        JavaCPP_log(\"Could not detach the JavaVM from the current thread.\");");
            out.println("    }");
            out.println("#endif");
            out.println("}");
            out.println();
            if (!loadSuffix.isEmpty()) {
                out.println("extern \"C\" {");
                out.println("JNIEXPORT jint JNICALL JNI_OnLoad" + loadSuffix + "(JavaVM* vm, void* reserved);");
                out.println("}");
            }
            out.println("static JavaCPP_noinline bool JavaCPP_getEnv(JNIEnv** env) {");
            out.println("    bool attached = false;");
            out.println("    JavaVM *vm = JavaCPP_vm;");
            out.println("    if (vm == NULL) {");
            if (out2 != null) {
                out.println("#if !defined(__ANDROID__) && !TARGET_OS_IPHONE");
                out.println("        int size = 1;");
                out.println("        if (JNI_GetCreatedJavaVMs(&vm, 1, &size) != JNI_OK || size == 0) {");
                out.println("#endif");
            }
            out.println("            JavaCPP_log(\"Could not get any created JavaVM.\");");
            out.println("            *env = NULL;");
            out.println("            return false;");
            if (out2 != null) {
                out.println("#if !defined(__ANDROID__) && !TARGET_OS_IPHONE");
                out.println("        }");
                out.println("#endif");
            }
            out.println("    }");
            out.println("    if (vm->GetEnv((void**)env, " + JNI_VERSION + ") != JNI_OK) {");
            out.println("        struct {");
            out.println("            JNIEnv **env;");
            out.println("            operator JNIEnv**() { return env; } // Android JNI");
            out.println("            operator void**() { return (void**)env; } // standard JNI");
            out.println("        } env2 = { env };");
            out.println("        if (vm->AttachCurrentThread(env2, NULL) != JNI_OK) {");
            out.println("            JavaCPP_log(\"Could not attach the JavaVM to the current thread.\");");
            out.println("            *env = NULL;");
            out.println("            return false;");
            out.println("        }");
            out.println("        attached = true;");
            out.println("    }");
            out.println("    if (JavaCPP_vm == NULL) {");
            out.println("        if (JNI_OnLoad" + loadSuffix + "(vm, NULL) < 0) {");
            out.println("            JavaCPP_detach(attached);");
            out.println("            *env = NULL;");
            out.println("            return false;");
            out.println("        }");
            out.println("    }");
            out.println("    return attached;");
            out.println("}");
            out.println();
        }
        for (Class c : functions) {
            String[] typeName = cppTypeName(c);
            String[] returnConvention = typeName[0].split("\\(");
            returnConvention[1] = constValueTypeName(returnConvention[1]);
            String parameterDeclaration = typeName[1].substring(1);
            String instanceTypeName = functionClassName(c);
            out.println("struct JavaCPP_hidden " + instanceTypeName + " {");
            out.println("    " + instanceTypeName + "() : ptr(NULL), obj(NULL) { }");
            if (parameterDeclaration != null && parameterDeclaration.length() > 0) {
                out.println("    " + returnConvention[0] + "operator()" + parameterDeclaration + ";");
            }
            out.println("    " + typeName[0] + "ptr" + typeName[1] + ";");
            out.println("    jobject obj; static jmethodID mid;");
            out.println("};");
            out.println("jmethodID " + instanceTypeName + "::mid = NULL;");
        }
        out.println();
        for (Class c : jclasses) {
            Set<String> functionList = virtualFunctions.get(c);
            if (functionList == null) {
                continue;
            }
            Set<String> memberList = virtualMembers.get(c);
            String[] typeName = cppTypeName(c);
            String valueTypeName = valueTypeName(typeName);
            String subType = "JavaCPP_" + mangle(valueTypeName);
            out.println("class JavaCPP_hidden " + subType + " : public " + valueTypeName + " {");
            out.println("public:");
            out.println("    jobject obj;");
            for (String s : functionList) {
                out.println("    static jmethodID " + s + ";");
            }
            out.println();
            for (String s : memberList) {
                out.println(s);
            }
            out.println("};");
            for (String s : functionList) {
                out.println("jmethodID " + subType + "::" + s + " = NULL;");
            }
        }
        out.println();
        for (String s : callbacks) {
            out.println(s);
        }
        out.println();
        for (Class c : deallocators) {
            String name = "JavaCPP_" + mangle(c.getName());
            out.print("static void " + name + "_deallocate(void *p) { ");
            if (FunctionPointer.class.isAssignableFrom(c)) {
                String typeName = functionClassName(c) + "*";
                out.println("JNIEnv *e; bool a = JavaCPP_getEnv(&e); if (e != NULL) e->DeleteWeakGlobalRef((jweak)(("
                        + typeName + ")p)->obj); delete (" + typeName + ")p; JavaCPP_detach(a); }");
            } else if (virtualFunctions.containsKey(c)) {
                String[] typeName = cppTypeName(c);
                String valueTypeName = valueTypeName(typeName);
                String subType = "JavaCPP_" + mangle(valueTypeName);
                out.println("JNIEnv *e; bool a = JavaCPP_getEnv(&e); if (e != NULL) e->DeleteWeakGlobalRef((jweak)(("
                        + subType + "*)p)->obj); delete (" + subType + "*)p; JavaCPP_detach(a); }");
            } else {
                String[] typeName = cppTypeName(c);
                out.println("delete (" + typeName[0] + typeName[1] + ")p; }");
            }
        }
        for (Class c : arrayDeallocators) {
            String name = "JavaCPP_" + mangle(c.getName());
            String[] typeName = cppTypeName(c);
            out.println("static void " + name + "_deallocateArray(void* p) { delete[] (" + typeName[0] + typeName[1] + ")p; }");
        }
        out.println();
        out.println("static const char* JavaCPP_members[" + jclasses.size() + "][" + maxMemberSize + 1 + "] = {");
        classIterator = jclasses.iterator();
        while (classIterator.hasNext()) {
            out.print("        { ");
            Set<String> m = members.get(classIterator.next());
            Iterator<String> memberIterator = m == null ? null : m.iterator();
            if (memberIterator == null || !memberIterator.hasNext()) {
                out.print("NULL");
            } else while (memberIterator.hasNext()) {
                out.print("\"" + memberIterator.next() + "\"");
                if (memberIterator.hasNext()) {
                    out.print(", ");
                }
            }
            out.print(" }");
            if (classIterator.hasNext()) {
                out.println(",");
            }
        }
        out.println(" };");
        out.println("static int JavaCPP_offsets[" + jclasses.size() + "][" + maxMemberSize + 1 + "] = {");
        classIterator = jclasses.iterator();
        while (classIterator.hasNext()) {
            out.print("        { ");
            Class c = classIterator.next();
            Set<String> m = members.get(c);
            Iterator<String> memberIterator = m == null ? null : m.iterator();
            if (memberIterator == null || !memberIterator.hasNext()) {
                out.print("-1");
            } else while (memberIterator.hasNext()) {
                String[] typeName = cppTypeName(c);
                String valueTypeName = valueTypeName(typeName);
                String memberName = memberIterator.next();
                if ("sizeof".equals(memberName)) {
                    if ("void".equals(valueTypeName)) {
                        valueTypeName = "void*";
                    }
                    out.print("sizeof(" + valueTypeName + ")");
                } else {
                    out.print("offsetof(" + valueTypeName  + ", " + memberName + ")");
                }
                if (memberIterator.hasNext()) {
                    out.print(", ");
                }
            }
            out.print(" }");
            if (classIterator.hasNext()) {
                out.println(",");
            }
        }
        out.println(" };");
        out.print("static int JavaCPP_memberOffsetSizes[" + jclasses.size() + "] = { ");
        classIterator = jclasses.iterator();
        while (classIterator.hasNext()) {
            Set<String> m = members.get(classIterator.next());
            out.print(m == null ? 1 : m.size());
            if (classIterator.hasNext()) {
                out.print(", ");
            }
        }
        out.println(" };");
        out.println();
        out.println("extern \"C\" {");
        if (out2 != null) {
            out2.println();
            out2.println("#ifdef __cplusplus");
            out2.println("extern \"C\" {");
            out2.println("#endif");
            out2.println("JNIIMPORT int JavaCPP_init" + loadSuffix + "(int argc, const char *argv[]);");
            out.println();
            out.println("JNIEXPORT int JavaCPP_init" + loadSuffix + "(int argc, const char *argv[]) {");
            out.println("#if defined(__ANDROID__) || TARGET_OS_IPHONE");
            out.println("    return JNI_OK;");
            out.println("#else");
            out.println("    if (JavaCPP_vm != NULL) {");
            out.println("        return JNI_OK;");
            out.println("    }");
            out.println("    int err;");
            out.println("    JavaVM *vm;");
            out.println("    JNIEnv *env;");
            out.println("    int nOptions = 1 + (argc > 255 ? 255 : argc);");
            out.println("    JavaVMOption options[256] = { { NULL } };");
            out.println("    options[0].optionString = (char*)\"-Djava.class.path=" + classPath.replace('\\', '/') + "\";");
            out.println("    for (int i = 1; i < nOptions && argv != NULL; i++) {");
            out.println("        options[i].optionString = (char*)argv[i - 1];");
            out.println("    }");
            out.println("    JavaVMInitArgs vm_args = { " + JNI_VERSION + ", nOptions, options };");
            out.println("    return (err = JNI_CreateJavaVM(&vm, (void**)&env, &vm_args)) == JNI_OK && vm != NULL && (err = JNI_OnLoad" + loadSuffix + "(vm, NULL)) >= 0 ? JNI_OK : err;");
            out.println("#endif");
            out.println("}");
        }
        if (baseLoadSuffix != null && !baseLoadSuffix.isEmpty()) {
            out.println();
            out.println("JNIEXPORT jint JNICALL JNI_OnLoad" + baseLoadSuffix + "(JavaVM* vm, void* reserved);");
            out.println("JNIEXPORT void JNICALL JNI_OnUnload" + baseLoadSuffix + "(JavaVM* vm, void* reserved);");
        }
        out.println(); // XXX: JNI_OnLoad() should ideally be protected by some mutex
        out.println("JNIEXPORT jint JNICALL JNI_OnLoad" + loadSuffix + "(JavaVM* vm, void* reserved) {");
        if (baseLoadSuffix != null && !baseLoadSuffix.isEmpty()) {
            out.println("    if (JNI_OnLoad" + baseLoadSuffix + "(vm, reserved) == JNI_ERR) {");
            out.println("        return JNI_ERR;");
            out.println("    }");
        }
        out.println("    JNIEnv* env;");
        out.println("    if (vm->GetEnv((void**)&env, " + JNI_VERSION + ") != JNI_OK) {");
        out.println("        JavaCPP_log(\"Could not get JNIEnv for " + JNI_VERSION + " inside JNI_OnLoad" + loadSuffix + "().\");");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    if (JavaCPP_vm == vm) {");
        out.println("        return env->GetVersion();");
        out.println("    }");
        out.println("    JavaCPP_vm = vm;");
        out.println("    JavaCPP_haveAllocObject = env->functions->AllocObject != NULL;");
        out.println("    JavaCPP_haveNonvirtual = env->functions->CallNonvirtualVoidMethodA != NULL;");
        out.println("    jmethodID putMemberOffsetMID = JavaCPP_getStaticMethodID(env, " +
                jclasses.index(Loader.class) + ", \"putMemberOffset\", \"(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/Class;\");");
        out.println("    if (putMemberOffsetMID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    for (int i = 0; i < " + jclasses.size() + " && !env->ExceptionCheck(); i++) {");
        out.println("        for (int j = 0; j < JavaCPP_memberOffsetSizes[i] && !env->ExceptionCheck(); j++) {");
        out.println("            if (env->PushLocalFrame(3) == 0) {");
        out.println("                jvalue args[3];");
        out.println("                args[0].l = env->NewStringUTF(JavaCPP_classNames[i]);");
        out.println("                args[1].l = JavaCPP_members[i][j] == NULL ? NULL : env->NewStringUTF(JavaCPP_members[i][j]);");
        out.println("                args[2].i = JavaCPP_offsets[i][j];");
        out.println("                jclass cls = (jclass)env->CallStaticObjectMethodA(JavaCPP_getClass(env, " +
                jclasses.index(Loader.class) + "), putMemberOffsetMID, args);");
        out.println("                if (cls == NULL || env->ExceptionCheck()) {");
        out.println("                    JavaCPP_log(\"Error putting member offsets for class %s.\", JavaCPP_classNames[i]);");
        out.println("                    return JNI_ERR;");
        out.println("                }");
        out.println("                JavaCPP_classes[i] = (jclass)env->NewWeakGlobalRef(cls);"); // cache here for custom class loaders
        out.println("                if (JavaCPP_classes[i] == NULL || env->ExceptionCheck()) {");
        out.println("                    JavaCPP_log(\"Error creating global reference of class %s.\", JavaCPP_classNames[i]);");
        out.println("                    return JNI_ERR;");
        out.println("                }");
        out.println("                env->PopLocalFrame(NULL);");
        out.println("            }");
        out.println("        }");
        out.println("    }");
        out.println("    JavaCPP_addressFID = JavaCPP_getFieldID(env, " +
                jclasses.index(Pointer.class) + ", \"address\", \"J\");");
        out.println("    if (JavaCPP_addressFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_positionFID = JavaCPP_getFieldID(env, " +
                jclasses.index(Pointer.class) + ", \"position\", \"J\");");
        out.println("    if (JavaCPP_positionFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_limitFID = JavaCPP_getFieldID(env, " +
                jclasses.index(Pointer.class) + ", \"limit\", \"J\");");
        out.println("    if (JavaCPP_limitFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_capacityFID = JavaCPP_getFieldID(env, " +
                jclasses.index(Pointer.class) + ", \"capacity\", \"J\");");
        out.println("    if (JavaCPP_capacityFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_deallocatorFID = JavaCPP_getFieldID(env, " +
                jclasses.index(Pointer.class) + ", \"deallocator\", \"" + signature(deallocator) + "\");");
        out.println("    if (JavaCPP_deallocatorFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_ownerAddressFID = JavaCPP_getFieldID(env, " +
                jclasses.index(nativeDeallocator) + ", \"ownerAddress\", \"J\");");
        out.println("    if (JavaCPP_ownerAddressFID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_initMID = JavaCPP_getMethodID(env, " +
                jclasses.index(Pointer.class) + ", \"init\", \"(JJJJ)V\");");
        out.println("    if (JavaCPP_initMID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_arrayMID = JavaCPP_getMethodID(env, " +
                jclasses.index(Buffer.class) + ", \"array\", \"()Ljava/lang/Object;\");");
        out.println("    if (JavaCPP_arrayMID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_stringMID = JavaCPP_getMethodID(env, " +
                jclasses.index(String.class) + ", \"<init>\", \"([B)V\");");
        out.println("    if (JavaCPP_stringMID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_getBytesMID = JavaCPP_getMethodID(env, " +
                jclasses.index(String.class) + ", \"getBytes\", \"()[B\");");
        out.println("    if (JavaCPP_getBytesMID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    JavaCPP_toStringMID = JavaCPP_getMethodID(env, " +
                jclasses.index(Object.class) + ", \"toString\", \"()Ljava/lang/String;\");");
        out.println("    if (JavaCPP_toStringMID == NULL) {");
        out.println("        return JNI_ERR;");
        out.println("    }");
        out.println("    return env->GetVersion();");
        out.println("}");
        out.println();
        if (out2 != null) {
            out2.println("JNIIMPORT int JavaCPP_uninit" + loadSuffix + "();");
            out2.println();
            out.println("JNIEXPORT int JavaCPP_uninit" + loadSuffix + "() {");
            out.println("#if defined(__ANDROID__) || TARGET_OS_IPHONE");
            out.println("    return JNI_OK;");
            out.println("#else");
            out.println("    JavaVM *vm = JavaCPP_vm;");
            out.println("    JNI_OnUnload" + loadSuffix + "(JavaCPP_vm, NULL);");
            out.println("    return vm->DestroyJavaVM();");
            out.println("#endif");
            out.println("}");
        }
        out.println();
        out.println("JNIEXPORT void JNICALL JNI_OnUnload" + loadSuffix + "(JavaVM* vm, void* reserved) {");
        out.println("    JNIEnv* env;");
        out.println("    if (vm->GetEnv((void**)&env, " + JNI_VERSION + ") != JNI_OK) {");
        out.println("        JavaCPP_log(\"Could not get JNIEnv for " + JNI_VERSION + " inside JNI_OnUnLoad" + loadSuffix + "().\");");
        out.println("        return;");
        out.println("    }");
        out.println("    for (int i = 0; i < " + jclasses.size() + "; i++) {");
        out.println("        env->DeleteWeakGlobalRef((jweak)JavaCPP_classes[i]);");
        out.println("        JavaCPP_classes[i] = NULL;");
        out.println("    }");
        if (baseLoadSuffix != null && !baseLoadSuffix.isEmpty()) {
            out.println("    JNI_OnUnload" + baseLoadSuffix + "(vm, reserved);");
        }
        out.println("    JavaCPP_vm = NULL;");
        out.println("}");
        out.println();

        boolean supportedPlatform = false;
        LinkedHashSet<Class> allClasses = new LinkedHashSet<Class>();
        if (baseLoadSuffix == null || baseLoadSuffix.isEmpty()) {
            supportedPlatform = true;
            allClasses.addAll(baseClasses);
        }

        if (classes != null) {
            allClasses.addAll(Arrays.asList(classes));

            for (Class<?> cls : classes) {
                supportedPlatform |= checkPlatform(cls);
            }
        }

        boolean didSomethingUseful = false;
        for (Class<?> cls : allClasses) {
            try {
                didSomethingUseful |= methods(cls);
            } catch (NoClassDefFoundError e) {
                logger.warn("Could not generate code for class " + cls.getCanonicalName() + ": " + e);
            }
        }

        out.println("}");
        out.println();
        if (out2 != null) {
            out2.println("#ifdef __cplusplus");
            out2.println("}");
            out2.println("#endif");
        }

        return supportedPlatform;
    }