как предотвратить вставку пустых данных в базу данных mysql из HTTP-запроса post

Кэширование JNIEnv* не является особенно хорошей идеей, поскольку вы не можете использовать один и тот же JNIEnv* для нескольких потоков и, возможно, даже не сможете использовать его для нескольких собственных вызовов в одном потоке (см. http://android-developers.blogspot.se/2011/11/jni-local-reference-changes-in-ics.html )

Написание функции, которая получает JNIEnv* и при необходимости присоединяет текущий поток к виртуальной машине:

bool GetJniEnv(JavaVM *vm, JNIEnv **env) {
    bool did_attach_thread = false;
    *env = nullptr;
    // Check if the current thread is attached to the VM
    auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
    if (get_env_result == JNI_EDETACHED) {
        if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
            did_attach_thread = true;
        } else {
            // Failed to attach thread. Throw an exception if you want to.
        }
    } else if (get_env_result == JNI_EVERSION) {
        // Unsupported JNI version. Throw an exception if you want to.
    }
    return did_attach_thread;
}

Способ использования:

JNIEnv *env;
bool did_attach = GetJniEnv(vm, &env);
// Use env...
// ...
if (did_attach) {
   vm->DetachCurrentThread();
}

Вы можете обернуть это в классе, который прикрепляется к конструкции и отделяется от разрушения, RAII-стиль:

class ScopedEnv {
public:
    ScopedEnv() : attached_to_vm_(false) {
        attached_to_vm_ = GetJniEnv(g_vm, &env_);  // g_vm is a global
    }

    ScopedEnv(const ScopedEnv&) = delete;
    ScopedEnv& operator=(const ScopedEnv&) = delete;

    virtual ~ScopedEnv() {
        if (attached_to_vm_) {
            g_vm->DetachCurrentThread();
            attached_to_vm_ = false;
        }
    }

    JNIEnv *GetEnv() const { return env_; }

private:
    bool attached_to_env_;
    JNIEnv *env_;
};

// Usage:

{
    ScopedEnv scoped_env;
    scoped_env.GetEnv()->SomeJniFunction();
}
// scoped_env falls out of scope, the thread is automatically detached if necessary

Редактирование: Иногда у вас может быть длинный и бедный родной поток, для которого потребуется JNIEnv* в нескольких случаях. В таких ситуациях вы можете избегать постоянного прикрепления и отсоединения нити к / из JVM, но вам все равно нужно убедиться, что вы отсоедините нить от разрушения резьбы.

Вы можете выполнить это, присоединив нить только один раз, а затем оставить его прикрепленным и установив обратный вызов уничтожения потока с помощью pthread_key_create и pthread_setspecific, который позаботится о вызове DetachCurrentThread.

/**
 * Get a JNIEnv* valid for this thread, regardless of whether
 * we're on a native thread or a Java thread.
 * If the calling thread is not currently attached to the JVM
 * it will be attached, and then automatically detached when the
 * thread is destroyed.
 */   
JNIEnv *GetJniEnv() {
    JNIEnv *env = nullptr;
    // We still call GetEnv first to detect if the thread already
    // is attached. This is done to avoid setting up a DetachCurrentThread
    // call on a Java thread.

    // g_vm is a global.
    auto get_env_result = g_vm->GetEnv((void**)&env, JNI_VERSION_1_6);
    if (get_env_result == JNI_EDETACHED) {
        if (g_vm->AttachCurrentThread(&env, NULL) == JNI_OK) {
            DeferThreadDetach(env);
        } else {
            // Failed to attach thread. Throw an exception if you want to.
        }
    } else if (get_env_result == JNI_EVERSION) {
        // Unsupported JNI version. Throw an exception if you want to.
    }
    return env;
}

void DeferThreadDetach(JNIEnv *env) {
    static pthread_key_t thread_key;

    // Set up a Thread Specific Data key, and a callback that
    // will be executed when a thread is destroyed.
    // This is only done once, across all threads, and the value
    // associated with the key for any given thread will initially
    // be NULL.
    static auto run_once = [] {
        const auto err = pthread_key_create(&thread_key, [] (void *ts_env) {
            if (ts_env) {
                g_vm->DetachCurrentThread();
            }
        });
        if (err) {
            // Failed to create TSD key. Throw an exception if you want to.
        }
        return 0;
    }();

    // For the callback to actually be executed when a thread exits
    // we need to associate a non-NULL value with the key on that thread.
    // We can use the JNIEnv* as that value.
    const auto ts_env = pthread_getspecific(thread_key);
    if (!ts_env) {
        if (pthread_setspecific(thread_key, env)) {
            // Failed to set thread-specific value for key. Throw an exception if you want to.
        }
    }
}

Если __cxa_thread_atexit доступный вам, вы можете выполнить одно и то же с некоторым объектом thread_local, который вызывает DetachCurrentThread в своем деструкторе.

0
задан Nurohman AR 3 March 2019 в 08:37
поделиться

1 ответ

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная [111] ключ file, и содержит ли

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная [111] ключ [112], и содержит ли [113] license_id, username и address.

if (isset(

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная [111] ключ file, и содержит ли

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная [111] ключ [112], и содержит ли [113] license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

GET
license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

FILES
ключ file, и содержит ли

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная [111] ключ [112], и содержит ли [113] license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

GET
license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

FILES['file'])) { die('Request invalid'); }

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

GET
license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

FILES
ключ file, и содержит ли

Подтвердить ввод.

Это может быть сделано разными способами. Одним из них может быть проверка, содержит ли глобальная переменная [111] ключ [112], и содержит ли [113] license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

GET
license_id, username и address.

[110]

PS. Как правило, использование глобальных переменных обременено угрозой безопасности. Что бы вы могли сделать, не подвергая его рефакторингу полностью, подумайте о добавлении пользовательского заголовка (например, X-Client: My Fancy CSharp Application) и проверке его внутри кода PHP.

0
ответ дан Haru 3 March 2019 в 08:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: