首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JVM在调用NETunnelProviderManager.loadAllFromPreferencesWithCompletionHandler时崩溃

JVM在调用NETunnelProviderManager.loadAllFromPreferencesWithCompletionHandler时崩溃
EN

Stack Overflow用户
提问于 2021-05-25 11:41:24
回答 1查看 99关注 0票数 1

我想从我的java应用程序中调用NetworkExtension框架函数。作为第一步,我打电话给NETunnelProviderManager.loadAllFromPreferencesWithCompletionHandler。我使用的是从源代码编译的罗可可图书馆 (0.8.3-快照)。

我的NETunnelProviderManager类如下:

代码语言:javascript
复制
package ai.safekids.infra.jna.ext.mac.networkextension;

import ai.safekids.infra.jna.ext.mac.data.NSArrayRef;
import ai.safekids.infra.jna.ext.mac.data.NSErrorRef;
import com.sun.jna.Callback;
import org.rococoa.Rococoa;
import org.rococoa.ObjCClass;
import org.rococoa.cocoa.foundation.NSArray;

public abstract class NETunnelProviderManager extends NEVPNManager {
    public static final _Class CLASS = Rococoa.createClass("NETunnelProviderManager", _Class.class);

    public interface LoadAllFromPreferencesCompletionHandler extends Callback {
        void callback(NSArrayRef managers, NSErrorRef error);
    }

    public static NETunnelProviderManager new_() {
        return Rococoa.create("NETunnelProviderManager", NETunnelProviderManager.class);
    }

    public interface _Class extends ObjCClass {
        void loadAllFromPreferencesWithCompletionHandler(LoadAllFromPreferencesCompletionHandler completionHandler);
    }

    public static void loadAllFromPreferencesWithCompletionHandler(LoadAllFromPreferencesCompletionHandler completionHandler) {
        CLASS.loadAllFromPreferencesWithCompletionHandler(completionHandler);
    }
}

而NEVPNManager类是:

代码语言:javascript
复制
package ai.safekids.infra.jna.ext.mac.networkextension;

import com.sun.jna.Callback;
import org.rococoa.Rococoa;
import org.rococoa.cocoa.foundation.NSError;
import org.rococoa.cocoa.foundation.NSObject;
import org.rococoa.ObjCClass;

public abstract class NEVPNManager extends NSObject {
    public static final _Class CLASS = Rococoa.createClass("NEVPNManager", _Class.class);

    public interface LoadFromPreferencesCompletionHandler extends Callback {
        void invoke(NSError error);
    }

    public interface _Class extends ObjCClass {
        NEVPNManager sharedManager();
    }

    public static NEVPNManager new_() {
        return Rococoa.create("NEVPNManager", NEVPNManager.class);
    }

    static public final NEVPNManager sharedManager = NEVPNManager.CLASS.sharedManager();

    static public NEVPNManager sharedManager() {
        return sharedManager;
    }

    public abstract void loadFromPreferencesWithCompletionHandler(LoadFromPreferencesCompletionHandler completionHandler);
}

使VM崩溃的单元测试是:

代码语言:javascript
复制
public void testLoadAllPreferences() throws Exception {

    NETunnelProviderManager.LoadAllFromPreferencesCompletionHandler completionHandler = new NETunnelProviderManager.LoadAllFromPreferencesCompletionHandler() {
        public void callback(NSArrayRef managers, NSErrorRef error) {
            Assert.assertEquals(true, true);
        }
    };

    NETunnelProviderManager.loadAllFromPreferencesWithCompletionHandler(completionHandler);
    TimeUnit.SECONDS.sleep(5);
}

我的NSArrayRef课程是

代码语言:javascript
复制
package ai.safekids.infra.jna.ext.mac.data;

import org.rococoa.ObjCObjectByReference;

public class NSArrayRef extends ObjCObjectByReference {
}

mvn test输出是

代码语言:javascript
复制
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running ai.safekids.infra.jna.ext.mac.NETunnelProviderManagerTest
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by net.sf.cglib.core.ReflectUtils$1 (file:/Users/mac/.m2/repository/cglib/cglib/3.3.0/cglib-3.3.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of net.sf.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fff2049ebc3, pid=12628, tid=5891
#
# JRE version: OpenJDK Runtime Environment (15.0.2+7) (build 15.0.2+7)
# Java VM: OpenJDK 64-Bit Server VM (15.0.2+7, mixed mode, sharing, tiered, compressed oops, g1 gc, bsd-amd64)
# Problematic frame:
# C  [libobjc.A.dylib+0x5bc3]  objc_retain+0x23
#
# No core dump will be written. 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:
# /Users/mac/code/safekids/packet-proxy/hs_err_pid12628.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
/bin/sh: line 1: 12628 Abort trap: 6           /usr/local/Cellar/openjdk/15.0.2/libexec/openjdk.jdk/Contents/Home/bin/java -jar /Users/mac/code/safekids/packet-proxy/target/surefire/surefirebooter783506685843365516.jar /Users/mac/code/safekids/packet-proxy/target/surefire/surefire517337276897757629tmp /Users/mac/code/safekids/packet-proxy/target/surefire/surefire_011227232066576961507tmp

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.094 s
[INFO] Finished at: 2021-05-25T16:31:12+05:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test) on project packet-proxy: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test failed: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ? -> [Help 1]

几个问题:

  • Rococoa支持回调吗?
  • VM崩溃的原因是什么,我如何修复它?
  • 是在LoadAllFromPreferencesCompletionHandler中使用NSError/NSArray还是在NSErrorRef/NSArrayRef中使用
EN

回答 1

Stack Overflow用户

发布于 2021-05-26 06:19:01

Rococoa主要是底层JNA库的一个面向对象的接口,它确实支持回调。

JVM崩溃的可能原因是您的回调超出了可访问范围。一旦在Java中执行了这一行,JVM编译器就认为您已经完成了completionHandler变量,并且它有资格进行垃圾收集。

代码语言:javascript
复制
NETunnelProviderManager.loadAllFromPreferencesWithCompletionHandler(completionHandler);

如果您使用的是JDK 9+,这是最容易用可达栅栏解决的。只需在回调后添加此行,以确保保留强引用:

代码语言:javascript
复制
Reference.reachabilityFence(completionHandler);

如果您正在使用JDK8或更早的版本,最好的解决方法是使用.最后阻止并对最后块中的对象执行一些操作,例如,

代码语言:javascript
复制
try {
    NETunnelProviderManager.loadAllFromPreferencesWithCompletionHandler(completionHandler);
    TimeUnit.SECONDS.sleep(5);
} finally {
    // do something with completionHandler
}

“做某事”可以是一个微不足道的执行(例如,一个toString()),您甚至不需要输出它,但是它将确保Java保持在对象上。

我在OpenJDK 8 (Hotspot)中读过的一种可能的“做某事”方法是在其他地方定义另一种方法,它的工作方式类似于JDK9 9+的可达性围栏。我还没有验证这一点;冒着自己的风险尝试它。这可能不适用于其他JVM。

代码语言:javascript
复制
static void reachabilityFence(Object obj) {
    // do nothing
}

另一种可能的解决方法是关闭回调,将其创建放在一个具有资源的试用块中,该块将保留引用,直到块完成并调用close() (可以是一个非op方法)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67687206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档