是否有可能“欺骗” Java程序,使任何字符串都误为null?

时间:2019-03-09 01:35:19

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

这是一个面试问题:

假设您正在为使用JNI和一些C ++代码从串行接口(例如uart)读取数据的Android系统进行编码。

最底层的东西将由C ++代码处理,最终数据将被馈送到Java接口,在此它将被视为String类型。

问题是:假设处理读取的Java代码是这样的:

private void parseSerialData(String input){

 if (input==null){
//DO SOMETHING HERE
    }
}

是否有可能满足if块的条件?

我对Java的理解告诉我,这是永远不可能的,因为(我可能完全错了)Java中的null是表示“没有引用”的方式,null不是对象,并且不是从类实例化。在DVM或JVM级别,只要声明了变量,就进行引用,即使堆栈上可能没有为其分配内存。

因此,作为方法的参数的局部变量不可能没有引用开头,更不用说稍后提供了指向String对象的引用(即使该对象可能没有引用)信息,它仍然是一个非null的对象),因此if条件将永远不会满足。

但是我不能确定这个问题是否是一个技巧问题,我已经省略了一些内容吗?尤其是考虑到存在C ++,而且我完全不知道将C ++空引用传递给Java是什么感觉?

那么,是否会满足if条件?

1 个答案:

答案 0 :(得分:3)

是的,input当然可以为空。它仅取决于C ++代码的功能。这是一个完整的例子。从您的描述中还不清楚本机方法是返回String还是将其作为参数从本机方法传递给java方法,因此我提供了每个示例。

此程序调用{​​{1}}五次。前三遍只是传递一个恒定值。接下来的两次等待输入(在本机方法中),然后根据输入是否为空而将null或非null传递给f

Test.java

f

Test.cc

public class Test
{
    static {
        System.loadLibrary("Test");
    }

    public static void main(String [] args)
    {
        Test obj = new Test();
        obj.main();
    }

    void main()
    {
        f(null);
        f("not null");
        String s1 = null;
        f(s1);
        String s2 = n1();
        f(s2);
        n2();
    }

    public void f(String s)
    {
        if (s == null)
            System.out.println("null");
        else
            System.out.println(s);
    }

    native String n1();
    native void n2();
}

构建说明

#include <stdio.h>
#include <jni.h>
#include "Test.h"

static jstring get_string(JNIEnv *env);

JNIEXPORT jstring JNICALL Java_Test_n1(JNIEnv *env, jobject obj)
{
    return get_string(env);
}

JNIEXPORT void JNICALL Java_Test_n2(JNIEnv *env, jobject obj)
{
    jstring s = get_string(env);
    jclass cls = env->GetObjectClass(obj);
    jmethodID f = env->GetMethodID(cls, "f", "(Ljava/lang/String;)V");
    env->CallVoidMethod(obj, f, s);
}

static jstring get_string(JNIEnv *env)
{
    char buf[20];
    if (fgets(buf, sizeof buf, stdin) == NULL)
        return NULL;
    if (buf[0] == '\n')
        return NULL;
    return env->NewStringUTF(buf);
}