是否有可能 "trick" 一个 Java 程序将任何字符串误认为空值?

Is it ever possible to "trick" a Java program into mistaking any string for null?

这是一道面试题:

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

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

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

private void parseSerialData(String input){

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

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

我对 Java 的理解告诉我这永远不可能,因为(我可能完全错了)Java 中的 null 是命名 "there is no reference" 的方式,null 不是' t 一个对象,它不是从 class 实例化的。在 DVM 或 JVM 级别,只要声明了一个变量,就进行了引用,即使堆栈上可能没有为其分配内存。

因此,作为方法参数的局部变量不可能没有引用开始,更不用说后来给它一个引用,它指向一个String对象(即使这个对象可能没有任何信息,它仍然是一个非空对象),因此,永远不会满足 if 条件。

但是我无法确定这道题是不是一道题,我漏掉了什么?特别是考虑到存在 C++,我不知道将 C++ 空引用传递给 Java 是什么感觉,是否有意义?

那么,if 条件会永远满足吗?

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

此程序调用 f 五次。前三次只是传递一个常量值。以下两次等待输入(在本机方法中)并根据输入是否为空将 null 或非 null 传递给 f

Test.java

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();
}

Test.cc

#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);
}

构建说明

$ javac Test.java
$ javah Test
$ gcc --std=c++11 -I $JAVA_HOME/include -I $JAVA_HOME/include/linux  -fPIC -shared -o libTest.so Test.cc
$ /usr/bin/java -Djava.library.path=. Test