日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本文介紹了JNA回調(diào)在對本機(jī)庫的特定內(nèi)部方法調(diào)用中間歇性地使應(yīng)用程序崩潰的處理方法,對大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

在我的應(yīng)用程序中,我使用JNA來使用用C編寫的本機(jī)代碼,在回調(diào)中我從本機(jī)應(yīng)用程序獲得通知。

在回調(diào)中,我得到一個指針和一些其他要處理的數(shù)據(jù)。在JNA回調(diào)代碼中,我必須再次使用該指針來調(diào)用其他本機(jī)庫代碼,并且必須傳遞該指針。之后,我必須從該回調(diào)返回。

如果我不從回調(diào)調(diào)用中間本機(jī)庫方法(傳遞指針),它工作得很好,但如果我添加這個調(diào)用,我的應(yīng)用程序會間歇性地崩潰(主要是在處理了數(shù)百個回調(diào)請求之后,有時(shí)它也成功地運(yùn)行了數(shù)千個回調(diào))。

在本機(jī)代碼中為其設(shè)置掛鉤的NotificationHook類對象是一個靜態(tài)變量,因?yàn)閼?yīng)用程序?qū)⒅挥幸粋€掛鉤。和本地庫逐一調(diào)用。

public interface INotificationHook extends Callback {

  public int NotificationHook(TRANX htrans, NOTIFICATION.ByReference notification);

}


public class NotificationHook implements INotificationHook {

    @Override
    public int NotificationHook(final TRANX tranx, final NOTIFICATION.ByReference notification) {
       System.out.println("Enter Java Callback");
       // notification contains actual data to process
       library.SendSrvcResponse(tranx); // if I put this method call, application crashes intermittently

       System.out.println("Exit Java Callback");
       return 0;
    }

}

Tranx本地結(jié)構(gòu):

typedef struct tagTRANX { int unused; } *TRANX;

TRANX.java

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;

@FieldOrder({"unused"})
public class TRANX extends Structure {

  public static class ByReference extends TRANX implements Structure.ByReference {
  }

  public static class ByValue extends TRANX implements Structure.ByValue {
  }

  public int unused = 0;

  public TRANX () {
    super();
  }

  public TRANX(final int unused) {
    super();
    this.unused = unused;
  }

  public TRANX(final Pointer peer) {
    super(peer);
  }
}

JNA中的庫定義(Java):

int SendSrvcResponse(TRANX tranx);

該指針實(shí)際上是一個結(jié)構(gòu)指針,我嘗試創(chuàng)建一個結(jié)構(gòu)并將該指針替換為該指針,即使在這種情況下應(yīng)用程序也會崩潰。

當(dāng)我添加很少的進(jìn)出日志時(shí),觀察結(jié)果如下:

printf("Enter to JNA from c library for callback");
hs = (*piHook->hookProc) (
tranx, notification); 
printf("Callback completed from JNA and returned to c library");

中間調(diào)用c庫:

SendSrvcResponse(TRANX tranx) {
    printf("Enter to send response in c library");
    // do some operation
    printf("Enter to send response in c library");
}

每次成功執(zhí)行時(shí),這是我從控制臺(集合JNA和C庫)的打印日志中獲得的信息:

    從c庫進(jìn)入JNA//C庫調(diào)用JNA回調(diào)
    輸入Java回調(diào)//Java回調(diào)調(diào)用Enter發(fā)送
    c庫中的響應(yīng)//調(diào)用本機(jī)庫中的方法發(fā)送
    在c庫中回車以發(fā)送響應(yīng)//本機(jī)庫中的方法在發(fā)送響應(yīng)后退出
    退出Java回調(diào)//Java
    回調(diào)完成其操作
    JNA回調(diào)完成后返回到c庫//,將流程返回到c庫
    代碼

在應(yīng)用程序崩潰的情況下,打印日志中缺少最后一條語句。只有JNA將方法流返回給C,但C不會接收它。

其中通知是指針。

崩潰日志:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000ffff6c78f610, pid=6396, tid=0x0000ffff6d9f0ac8
#
# JRE version: OpenJDK Runtime Environment (8.0_272-b10) (build 1.8.0_272-b10)
# Java VM: OpenJDK 64-Bit Server VM (25.272-b10 mixed mode linux-aarch64 compressed oops)
# Derivative: IcedTea 3.17.0
# Distribution: Custom build (Fri Dec 11 01:04:16 UTC 2020)
# Problematic frame:
# C  [jna791751318727750086.tmp+0xa610]  Java_com_sun_jna_Native_setByte+0x50
#
# Core dump written. Default location: **************
#
# If you would like to submit a bug report, please include
# instructions on how to reproduce the bug and visit:
#   https://icedtea.classpath.org/bugzilla
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  T H R E A D  ---------------

Current thread (0x0000ffff6c7b7000):  JavaThread "Thread-5356" [_thread_in_native, id=6642, stack(0x0000ffff6d9d0000,0x0000ffff6d9f0ac8)]

siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000ffff6c2ec018

Registers:
R0=0x0000000000000000
R1=0x0000000000000000
R2=0x0000ffff6c2ec018
R3=0x0000000000000000
R4=0x0000000000000000
R5=0x0000000000000000
R6=0x0000ffff66b49458
R7=0x0000ffff66b49458
R8=0x0000ffff6c78f5c0
R9=0x0000ffff6c7b72c8
R10=0x0000000020002230
R11=0x00000000f212dde8
R12=0x0000ffff691637f0
R13=0x0000000020002230
R14=0x00000000f212e4e0
R15=0x00000000f213acd0
R16=0x00000001006c7770
R17=0x0000000000000000
R18=0x0000000000000001
R19=0x0000ffff6c7aa250
R20=0x0000000000000000
R21=0x00000000f212e2b0
R22=0x0000000100781ed8
R23=0x00000000f212fd60
R24=0x00000000f213a868
R25=0x00000001000016d0
R26=0x00000000f213a880
R27=0x0000000000000000
R28=0x0000ffff6c7b7000
R29=0x0000ffff6d9efcd0
R30=0x0000ffff78fea394

Top of Stack: (sp=0x0000ffff6d9efcd0)
0x0000ffff6d9efcd0:   0000ffff6d9efd60 0000ffff78fea394
0x0000ffff6d9efce0:   00000000200f03db 0000000000000000
0x0000ffff6d9efcf0:   0000ffff6c2ec018 0000000000000000
0x0000ffff6d9efd00:   0000ffff6c7b7250 00aebfc8f212dfd8
0x0000ffff6d9efd10:   00000000f212dde8 00000000f21343b0
0x0000ffff6d9efd20:   00000000f21342f0 00000000f2134350
0x0000ffff6d9efd30:   00000000f2134368 00000000f2134380
0x0000ffff6d9efd40:   00000000f2134320 00000000f2134398
0x0000ffff6d9efd50:   00000000fca7ebc8 0000ffff77adb000
0x0000ffff6d9efd60:   0000ffff6d9f0220 0000ffff7988acb4
0x0000ffff6d9efd70:   00000000f21343c8 00000000f213a978
0x0000ffff6d9efd80:   0000ffff6d9f0220 0000ffff79952fbc
0x0000ffff6d9efd90:   00000000f213aa28 00000000f213aa68
0x0000ffff6d9efda0:   0000000000000000 00000000f213aae8
0x0000ffff6d9efdb0:   0000ffff6d9efdd0 0000ffff80d78678
0x0000ffff6d9efdc0:   0000000000000000 00000001000115f0
0x0000ffff6d9efdd0:   00000000fc391290 00000000f212e4e0
0x0000ffff6d9efde0:   00000000f212dfd8 00000000fc3a3960
0x0000ffff6d9efdf0:   00000000200eada6 0000000000000000
0x0000ffff6d9efe00:   00000000f21342e0 0000ffff6c7b7000
0x0000ffff6d9efe10:   00000000fc43c670 00000000d024ce28
0x0000ffff6d9efe20:   0000ffff6d9f0220 0000ffff799275fc
0x0000ffff6d9efe30:   00000000f212e4e0 00000000f212fb00
0x0000ffff6d9efe40:   00000000d0d14760 00000000d0d14760
0x0000ffff6d9efe50:   00000000f2131bc0 f212f75000000000
0x0000ffff6d9efe60:   0000ffff6d9f0220 0000ffff78eccdd8
0x0000ffff6d9efe70:   00000000f2131c20 00000000f212e398
0x0000ffff6d9efe80:   0000ffff6d9f0220 0000ffff79463d2c
0x0000ffff6d9efe90:   200f03db00000000 0000000100781ed8
0x0000ffff6d9efea0:   00000000f213acb0 00000000f21342e0
0x0000ffff6d9efeb0:   00000000f212e398 0000000000000000
0x0000ffff6d9efec0:   00000000f212e4e0 0000000000000000 

Instructions: (pc=0x0000ffff6c78f610)
0x0000ffff6c78f5f0:   e1 ff 00 91 1f 00 01 eb a3 02 00 54 e2 0f 42 a9
0x0000ffff6c78f600:   c0 00 00 f0 00 40 09 91 e1 ff 40 39 00 20 42 b9
0x0000ffff6c78f610:   41 68 23 38 e0 00 00 34 e0 1b 40 f9 22 00 00 b0
0x0000ffff6c78f620:   21 00 00 b0 42 80 30 91 21 e0 30 91 45 e5 ff 97 

Register to memory mapping:

R0=0x0000000000000000
R1=0x0000000000000000
R2=0x0000ffff6c2ec018
R3=0x0000000000000000
R4=0x0000000000000000
R5=0x0000000000000000
R6=0x0000ffff66b49458
R7=0x0000ffff66b49458
R8=0x0000ffff6c78f5c0
R9=0x0000ffff6c7b72c8
R10=0x0000000020002230
R11=0x00000000f212dde8
R12=0x0000ffff691637f0
R13=0x0000000020002230
R14=0x00000000f212e4e0
R15=0x00000000f213acd0
R16=0x00000001006c7770
R17=0x0000000000000000
R18=0x0000000000000001
R19=0x0000ffff6c7aa250
R20=0x0000000000000000
R21=0x00000000f212e2b0
R22=0x0000000100781ed8
R23=0x00000000f212fd60
R24=0x00000000f213a868
R25=0x00000001000016d0
R26=0x00000000f213a880
R27=0x0000000000000000
R28=0x0000ffff6c7b7000
R29=0x0000ffff6d9efcd0
R30=0x0000ffff78fea394


Stack: [0x0000ffff6d9d0000,0x0000ffff6d9f0ac8],  sp=0x0000ffff6d9efcd0,  free space=127k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [jna791751318727750086.tmp+0xa610]  Java_com_sun_jna_Native_setByte+0x50
J 5174  com.sun.jna.Native.setByte(Lcom/sun/jna/Pointer;JJB)V (0 bytes) @ 0x0000ffff78fea394 [0x0000ffff78fea300+0x94]
V  [libjvm.so+0x40f678]
C  0x00000000f212e4e0

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J 5174  com.sun.jna.Native.setByte(Lcom/sun/jna/Pointer;JJB)V (0 bytes) @ 0x0000ffff78fea398 [0x0000ffff78fea300+0x98]
J 9695 C2 com.sun.jna.Pointer.setByte(JB)V (11 bytes) @ 0x0000ffff7988acb4 [0x0000ffff7988ac80+0x34]
J 9266 C2 com.sun.jna.Pointer.setValue(JLjava/lang/Object;Ljava/lang/Class;)V (607 bytes) @ 0x0000ffff79952fbc [0x0000ffff79951ec0+0x10fc]
J 9230 C2 com.sun.jna.Structure.writeField(Lcom/sun/jna/Structure$StructField;)V (427 bytes) @ 0x0000ffff799275fc [0x0000ffff79927500+0xfc]
J 9423 C2 com.sun.jna.Structure.write()V (126 bytes) @ 0x0000ffff79463d2c [0x0000ffff79463840+0x4ec]
J 9434 C2 com.sun.jna.Structure.autoWrite()V (45 bytes) @ 0x0000ffff7904e274 [0x0000ffff7904e240+0x34]
J 9905 C1 com.sun.jna.CallbackReference$DefaultCallbackProxy.invokeCallback([Ljava/lang/Object;)Ljava/lang/Object; (238 bytes) @ 0x0000ffff78ee17c4 [0x0000ffff78ede580+0x3244]
J 9904 C1 com.sun.jna.CallbackReference$DefaultCallbackProxy.callback([Ljava/lang/Object;)Ljava/lang/Object; (22 bytes) @ 0x0000ffff78fa18b0 [0x0000ffff78fa1800+0xb0]
v  ~StubRoutines::call_stub

我嘗試過的內(nèi)容:

    在JNA回調(diào)輸入中用指針替換Tranx。
    在Java回調(diào)方法的最后一行對結(jié)構(gòu)調(diào)用clear()。
    在JNA中注釋完整的處理回調(diào)代碼,只保留對SendSrvcResponse方法的調(diào)用并返回回調(diào)。

所有這些都會導(dǎo)致崩潰,沒有一個是有幫助的。

一個奇怪的觀察是,當(dāng)在本機(jī)C代碼中實(shí)現(xiàn)此回調(diào)時(shí),應(yīng)用程序不會中斷。只有在與JNA集成時(shí)才會中斷。

有人能幫我了解一下這一事件的可能原因嗎?或者我怎樣才能進(jìn)一步調(diào)查它?

推薦答案

根據(jù)您提供的代碼,問題與這里的其他回調(diào)相關(guān)問題相同:由于JAVA的垃圾回收,您正在丟失TRANX的本機(jī)分配。

JNAStructure由兩部分組成:(指向數(shù)據(jù)的)指針和數(shù)據(jù)本身。您尚未為TRANX提供本機(jī)typlef來確認(rèn)您的JNA映射,但實(shí)例化的對象將有一個內(nèi)部指針引用,指向4字節(jié)的內(nèi)存分配(int unused)。

您只顯示回調(diào)代碼,其中TRANX已經(jīng)是一個參數(shù),這意味著您已經(jīng)將其實(shí)例化以傳遞給回調(diào)。

如果您使用new TRANX()new TRANX(int unused)自己分配它,則JNA已

分配了4字節(jié)的本機(jī)內(nèi)存
在內(nèi)部存儲指向它的指針

在JNA中,附加到Structure的本機(jī)內(nèi)存作為垃圾收集過程的一部分被自動釋放。這是回調(diào)的常見問題,因?yàn)槟ǔ2豢刂苹卣{(diào)返回的時(shí)間,因此會出現(xiàn)以下順序:

在Java中創(chuàng)建對象(分配TRANX結(jié)構(gòu)在內(nèi)部跟蹤指針?biāo)赶虻谋緳C(jī)4字節(jié))
TRANX對象傳遞給回調(diào)
傳遞對象后,Java立即不再需要自己的對象;它是不可訪問的,因此有資格進(jìn)行垃圾回收
發(fā)生GC時(shí),本機(jī)4字節(jié)作為進(jìn)程的一部分被釋放
回調(diào)中的TRANX對象在內(nèi)部仍有指針,但它現(xiàn)在指向不再分配的內(nèi)存,從而導(dǎo)致SIGSEGV(或無效內(nèi)存訪問錯誤,或由另一個線程分配內(nèi)存時(shí)出現(xiàn)奇怪癥狀,或其他未定義的行為)。

該問題的解決方案是跟蹤與TRANX關(guān)聯(lián)的內(nèi)存。

如果您自己分配它,請保留對TRANX對象的引用,以防止它無法到達(dá)。

這通常需要在您確定回調(diào)將被處理之后訪問TRANX結(jié)構(gòu)
在JDK9+中,ReachabilityFence可用于此。
在JDK8中,您應(yīng)該以某種方式操作類(例如,從類中讀取值,或?qū)ζ湔{(diào)用toString等)。

如果您使用本機(jī)分配并使用從本機(jī)API返回的peer值創(chuàng)建指針,則讀取API以確定何時(shí)釋放該內(nèi)存。

這篇關(guān)于JNA回調(diào)在對本機(jī)庫的特定內(nèi)部方法調(diào)用中間歇性地使應(yīng)用程序崩潰的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,

分享到:
標(biāo)簽:回調(diào) 在對 應(yīng)用程序 機(jī)庫 特定 調(diào)用 間歇性
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定