非常感谢你阅读这篇文章,
我正在使用java和c开发一个匿名聊天应用。我决定使用jni将c代码集成到java中。当我尝试建立连接并发送数据包时,它会因提到的错误而崩溃。我在网上搜索太多,但没有什么可以解决这个问题。我认为在C代码的某处我提交了一个关键的访问冲突或我编写的jni代码缺少部分。再次感谢您的大力帮助。这是错误消息和涉及的代码片段。
错误日志文件链接 https://www.dropbox.com/s/oy4k5uwz7mbyqiw/hs_err_pid13072.log?dl=0
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f21816b7d18, pid=13072, tid=0x00007f212eb1c700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_92-b14) (build 1.8.0_92-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V [libjvm.so+0x6dfd18] jni_GetStringUTFChars+0xb8
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/burhan/workspace/AnonymousChatApplication/hs_err_pid13072.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
/home/burhan/workspace/AnonymousChatApplication/nbproject/build-impl.xml:1039: The following error occurred while executing this line:
/home/burhan/workspace/AnonymousChatApplication/nbproject/build-impl.xml:804: Java returned: 134
BUILD FAILED (total time: 8 seconds)
错误输出消息
static {
System.loadLibrary("Send");
}
public void sending(String ip, String message){
int i=0;
for(String s:splitMessage(message)){
sender(2, ip, String.valueOf(i++)); // JNI NATIVE METHOD CALL
sender(2, ip, s); // JNI NATIVE METHOD CALL
}
}
以上部分是我称之为jni库的部分
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <jni.h>
#include "ChatUtility_PeerConnection.h"
#include <time.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#define MY_DEST_MAC0 0xFF
#define MY_DEST_MAC1 0xFF
#define MY_DEST_MAC2 0xFF
#define MY_DEST_MAC3 0xFF
#define MY_DEST_MAC4 0xFF
#define MY_DEST_MAC5 0xFF
#define BUF_SIZE 1500
#define DEFAULT_IF "eth0"
struct pseudo_header {
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t udp_length;
};
unsigned short csum(unsigned short *ptr, int nbytes) {
register long sum;
unsigned short oddbyte;
register short answer;
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((u_char*) &oddbyte) = *(u_char*) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum = sum + (sum >> 16);
answer = (short) ~sum;
return (answer);
}
JNIEXPORT void JNICALL Java_ChatUtility_PeerConnection_sender
(JNIEnv *env, jclass jClass, jint arg1, jstring arg2, jstring arg3){
int sockfd;
struct ifreq if_idx;
struct ifreq if_mac;
int tx_len = 0;
int pack_Id = 12345;
const char *peerIP = (*env)->GetStringUTFChars(env,arg2,0);
const char *message = (*env)->GetStringUTFChars(env,arg3,0);
srand(time(NULL));
pack_Id = rand();
char destination_ip[32];
strcpy(destination_ip, peerIP);
/* packet */
char sendbuf[BUF_SIZE];
/* zero out the packet */
memset(sendbuf, 0, BUF_SIZE);
/* ethernet header */
struct ether_header *eh = (struct ether_header *) sendbuf;
/* ip header */
struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));
/* udp header */
struct udphdr *udph = (struct udphdr *) (sendbuf + sizeof(struct ether_header) + sizeof(struct iphdr));
/* data */
char *data = sendbuf + sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct udphdr);
struct sockaddr_ll socket_address;
char ifName[IFNAMSIZ];
/* Get interface name */
strcpy(ifName, DEFAULT_IF);
/* get data */
if (arg1 > 1)
strcpy(data, message);
else
strcpy(data, "Message Not Captured");
/* Open RAW socket to send on */
if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
perror("Socket Error");
}
int broadcast = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) == -1) {
perror("Failed to broadcast");
exit(1);
}
/* Get the index of the interface to send on */
memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, ifName, IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)
perror("SIOCGIFINDEX");
/* Get the MAC address of the interface to send on */
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, ifName, IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
perror("SIOCGIFHWADDR");
/* Ethernet header */
eh->ether_shost[0] = 0xAA;
eh->ether_shost[1] = 0xBB;
eh->ether_shost[2] = 0xCC;
eh->ether_shost[3] = 0xDD;
eh->ether_shost[4] = 0xEE;
eh->ether_shost[5] = 0xFF;
eh->ether_dhost[0] = MY_DEST_MAC0;
eh->ether_dhost[1] = MY_DEST_MAC1;
eh->ether_dhost[2] = MY_DEST_MAC2;
eh->ether_dhost[3] = MY_DEST_MAC3;
eh->ether_dhost[4] = MY_DEST_MAC4;
eh->ether_dhost[5] = MY_DEST_MAC5;
/* Ethertype field */
eh->ether_type = htons(ETH_P_IP);
/* Index of the network device */
socket_address.sll_ifindex = if_idx.ifr_ifindex;
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = MY_DEST_MAC0;
socket_address.sll_addr[1] = MY_DEST_MAC1;
socket_address.sll_addr[2] = MY_DEST_MAC2;
socket_address.sll_addr[3] = MY_DEST_MAC3;
socket_address.sll_addr[4] = MY_DEST_MAC4;
socket_address.sll_addr[5] = MY_DEST_MAC5;
char source_ip[32], *pseudogram;
struct pseudo_header psh;
strcpy(source_ip, "1.2.3.4"); // Spoofed IP
/* IP Header */
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + strlen(data));
iph->id = htons(pack_Id); //ID of this packet
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_UDP;
iph->check = 0; //Set to 0 before calculating checksum
iph->saddr = inet_addr(source_ip);
iph->daddr = inet_addr(destination_ip); // Destination IP Address
/* IP Checksum */
iph->check = csum((unsigned short *) iph, 20);
/* UDP Header */
udph->source = htons(7777);
udph->dest = htons(7777);
udph->len = htons(8 + strlen(data));
udph->check = 0; //Set to 0 before calculating checksum
/* UDP Checksum Pseudoheader */
psh.source_address = inet_addr(source_ip);
psh.dest_address = inet_addr(destination_ip); // Destination IP Address
psh.placeholder = 0;
psh.protocol = IPPROTO_UDP;
psh.udp_length = htons(sizeof(struct udphdr) + strlen(data));
int psize = sizeof(struct pseudo_header) + sizeof(struct udphdr) + strlen(data);
pseudogram = malloc(psize);
memcpy(pseudogram, (char*) &psh, sizeof(struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header), udph, sizeof(struct udphdr) + strlen(data));
/* Set the UDP Checksum */
udph->check = csum((unsigned short*) pseudogram, psize);
/* Final transmit length in bytes */
tx_len = sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct udphdr) + strlen(data);
/* Send Packet */
if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*) &socket_address, sizeof(struct sockaddr_ll)) < 0) {
printf("Send failed\n");
}
else {
printf("Packet sent! (%d bytes)\n", tx_len);
}
//return 0;
(*env)->ReleaseStringUTFChars(env, arg2, peerIP);
(*env)->ReleaseStringUTFChars(env, arg3, message);
}
C中的Jni库函数
答案 0 :(得分:0)
我认为问题在于:
const char * peerIP =(* env) - &gt; GetStringUTFChars(env,arg2,0);
最后一个参数shout是指向jboolean的指针,而不是0。
此外,如果你使用jni,-Xcheck:jni
应该是你的朋友=)
好的,如果你试试
jboolean isCopy1;
jboolean isCopy2;
const char *peerIP = (*env)->GetStringUTFChars(env, arg2, &isCopy1);
const char *message = (*env)->GetStringUTFChars(env, arg3, &isCopy2);
在崩溃转储中,什么将位于本机堆栈的顶部?
是不是?V [libjvm.so + 0x6dfd18] jni_GetStringUTFChars + 0xb8