如何在C ++中正确地重用JNI JVM?

时间:2013-12-13 04:01:14

标签: java c++ linux java-native-interface

我有一个C ++类,它使用JNI JVM来运行Java方法。无论出于何种原因,我的程序正在进行3次迭代,在第3次循环中,JVM与SIGSEGV崩溃。

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f2af5de1c81, pid=7669, tid=139822523557696
#
# JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.45-b08 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libc.so.6+0x7ac81]

此代码根本不完整。

#include <string>
#include <thread>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#include "imgsearch.h"

#define PORT "8675"
#define BACKLOG 10

JNIEnv* create_vm() {
    JavaVM* j;
    JNIEnv* e;
    JavaVMInitArgs j_args;
        JavaVMOption opts;
        j_args.version = JNI_VERSION_1_6;
        j_args.nOptions = 1;
        j_args.ignoreUnrecognized = 0;
        char* cp = (char *)"-Djava.class.path=.:./lucene-4.4.0/analysis/common/lucene-analyzers-common-4.4.0.jar:./lucene-4.4.0/core/lucene-core-4.4.0.jar:./lucene-4.4.0/queryparser/lucene-queryparser-4.4.0.jar";
        opts.optionString = cp;
        j_args.options = &opts;
        JNI_CreateJavaVM(&j, (void**)&e, &j_args);

    return e;
}

JNIEnv* env = create_vm();
JavaVM* jvm;

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

void sockcom(int csock) {
        std::cout << "Yeah!" << std::endl;
}

int main(int argc, char *argv[]) {
    env->GetJavaVM(&jvm);
    std::string fP = "features/esp.feature";

    ImgSearch *iS;
    iS = new ImgSearch();
    iS->LoadFeatures(fP);
    //iS->BuildClusters(150000, 15);
    //iS->ClustersToFile("output.clusters");
    iS->FileToClusts("output.clusters");
    iS->BuildIndex();
    //iS->IndexToFile("output.index");
    //iS->FileToIndex("output.index");
    //iS->FindNeighbors();
    //iS->NeighborsToFile("output.neighbors");
    iS->FileToNeighbors("output.neighbors");
    iS->BagOfWords("features/imglist.txt", "features/esp.size", "coll/output.bagofwords");
    iS->BuildLuceneIndex("coll/output.bagofwords");
    //std::string queryfile = "queries/query1.pgm";

    int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;
    char s[INET6_ADDRSTRLEN];
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP

    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }

        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }

        break;
    }

    if (p == NULL)  {
        fprintf(stderr, "server: failed to bind\n");
        return 2;
    }

    freeaddrinfo(servinfo); // all done with this structure

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); }

    printf("server: waiting for connections...\n");

    while(1) { // main accept() loop
        int pipefd[2];
        int pres = pipe(pipefd);
        if (pres < 0) {
            perror("pipe");
            continue;
        }

        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
        if (new_fd == -1) {
            perror("accept");
            continue;
        }

        inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
        printf("server: got connection from %s\n", s);

        std::thread th(sockcom, new_fd);
        th.detach();

        std::string queryfile = "queries/query3.pgm";
        iS->Search(queryfile);
    }

    jvm->DestroyJavaVM();

    return 0;
}

所以iS-&gt;搜索(queryfile);基本上如下:

void ImgSearch::Search(std::string &filePath) {
    ImgQuery newQuery(filePath, Ndx, WORDS);
    newQuery.ExtractKeyPoints();
    newQuery.FindNeighbors();
    newQuery.BagOfWords();
    newQuery.LuceneSearch();

    return;
    // Error Checking?
}

LuceneSearch函数是唯一使用JNI JVM的函数。

void ImgQuery::LuceneSearch() {
    jclass qcls = env->FindClass("BatchSearch");
    if (qcls == NULL) std::cout << "BatchSearch: Not Found." << std::endl;
    jmethodID qmid = env->GetStaticMethodID(qcls, "main", "()V");
    env->CallStaticVoidMethod(qcls, qmid);

    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
    }

    std::cout << "Still working..." << std::endl;

    return;
    // Error Checking?
}

基本上,我想知道的是A)你看到任何明显错误的东西吗?和B)如何在整个项目中正确地重用JVM?

编辑:有没有办法等待JVM准备好?

0 个答案:

没有答案