gpt4 book ai didi

Java 绿色线程通过 JNI 使用 UNIX ucontext 库。是否可以?

转载 作者:行者123 更新时间:2023-12-01 05:13:15 31 4
gpt4 key购买 nike

我正在使用 ucontext 开发一个简单的、具有教育意义的绿色(合作)基于量子的线程示例。但我面临着问题。下面提供的示例非常容易理解,我将感谢您为我提供的任何帮助:

TestApp.java:

public class TestApp extends UThreadApp {
public static void umain() {
System.out.println("umain");
}
}

UThreadApp.java:

import java.io.*;

public class UThreadApp {
public static void main(String[] args) {
long kernel = newContext();
long umain = newUThread("TestApp", "umain");
swap(kernel, umain);
System.out.println("main");
}

native static long newContext();
native static void swap(long oldc, long newc);
native static long newUThread(String className, String method);

static {
System.loadLibrary("uthread");
}
}

UThreadApp.c:

#include <stdlib.h>
#include <ucontext.h>

#include "UThreadApp.h"

typedef struct {
ucontext_t context;
unsigned char stack[SIGSTKSZ];
} *Context;

ucontext_t *kernelContext;

/*
* Class: UThreadApp
* Method: newContext
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_UThreadApp_newContext
(JNIEnv *env, jclass cls) {
kernelContext = malloc(sizeof(ucontext_t));
if (kernelContext == NULL)
RTError("newContext: malloc: couldn't allocate memory for kernelContext");
return (jlong) kernelContext;
}

/*
* Class: UThreadApp
* Method: swap
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_UThreadApp_swap
(JNIEnv *env, jclass cls, jlong oldc, jlong newc) {
if (swapcontext((ucontext_t *)oldc, (ucontext_t *)newc) == -1)
SysError("swap: swapcontext: couldn't switch context");
}

static JavaVM *jvm = NULL;

static void callback(jclass cls, jmethodID mid) {
if (jvm == NULL)
return;

JNIEnv *env = NULL;
jint res;
res = (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
if (res < 0)
RTError("Attach VM Thread failed");

/* JVM segfaults here */
(*env)->CallStaticVoidMethod(env, cls, mid);
//printf("umain\n");

(*jvm)->DetachCurrentThread(jvm);
}

typedef void (*uthread_func)();

/*
* Class: UThreadApp
* Method: newUThread
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_UThreadApp_newUThread
(JNIEnv *env, jclass cls, jstring className, jstring method) {

/* find the current jvm */
(*env)->GetJavaVM(env, &jvm);

Context ctx = malloc(sizeof(*ctx));
if (getcontext((ucontext_t *)ctx) == -1)
RTError("newUThread: getcontext");
sigdelset(&ctx->context.uc_sigmask, SIGALRM);
ctx->context.uc_link = kernelContext;
ctx->context.uc_stack.ss_sp = ctx->stack;
ctx->context.uc_stack.ss_size = SIGSTKSZ;

const char *str;
str = (*env)->GetStringUTFChars(env, className, NULL);
if (str == NULL)
RTError("newUThread: className: GetStringUTFChars");
jclass kls = (*env)->FindClass(env, str);
if (kls == NULL)
RTError("newUThread: FindClass: class not found");
(*env)->ReleaseStringUTFChars(env, className, str);

str = (*env)->GetStringUTFChars(env, method, NULL);
if (str == NULL)
RTError("newUThread: method: GetStringUTFChars");
jmethodID mid = (*env)->GetStaticMethodID(env, kls, str, "()V");
if (mid == NULL) {
RTError("newUThread: GetStaticMethodID: method not found");
}
(*env)->ReleaseStringUTFChars(env, method, str);

/* make global references */
jclass gkls = (*env)->NewGlobalRef(env, kls);
jmethodID gmid = (*env)->NewGlobalRef(env, mid);

makecontext((ucontext_t *)ctx, (uthread_func)callback, 2, gkls, gmid);

return (jlong) ctx;
}

代码创建kernelmain上下文,并准备umain方法作为新的用户线程。 swap 切换上下文、保存内核并运行 main。示例应打印:

umain

下一个

主要

但是在 (*env)->CallStaticVoidMethod(env, cls, mid) 执行 Java 回调时出现段错误。这种代码很容易用 C 语言编写,但是当我尝试用 Java 开发它时,我遇到了一些微妙的问题。

Apache 的 javaflow 不是一个选择,因为我发现开发具有时间量子的调度程序(使用 SIGALRM)非常困难。

有什么想法吗?

最佳答案

您不应该尝试将 jmethodID 设为全局引用。它是一个方法 ID,而不是引用。编译器应该提示这一点。尝试在模块中全局保留方法 ID。

关于Java 绿色线程通过 JNI 使用 UNIX ucontext 库。是否可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11725706/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com