【问题标题】:Is there any level of obfuscation which can "trick" instanceof?是否有任何级别的混淆可以“欺骗”instanceof?
【发布时间】:2012-10-16 13:59:36
【问题描述】:

我一直在玩这个,到目前为止,我还没有找到任何方法来隐藏或欺骗 instanceof 通过层层混淆隐藏其类型来返回 false,但这并不意味着这是不可能的,因为我远不是最了解 Java 的人。所以特地来请教专家。

我尝试了以下组合,在每种情况下,instanceof 运算符都能够识别对象的真实/基本类型。

public class Test {

    public static void main(String[] args) {
        Object o = new TestObject();
        printType("Base Class", o);

        o = (TestSuperObject)(new TestObject());
        printType("Super Class", o);

        o = (TestInterface)(new TestObject());
        printType("Interface", o);

        o = (TestInterface)((TestSuperObject3)(new TestObject3()));
        printType("Interface on Super Class", o);

        o = (TestSuperObject3)((TestInterface)(new TestObject3()));
        printType("Super Class on Interface", o);
    }


    private static void printType(String testCase, Object o) {
        System.out.println(testCase);
        System.out.println("TestObject:" + (o instanceof TestObject));
        System.out.println("TestObject2:" + (o instanceof TestObject2));
        System.out.println("TestObject3:" + (o instanceof TestObject3));
        System.out.println();
    }

}

这些类被定义为...

public class TestObject extends TestSuperObject implements TestInterface
public class TestObject2 extends TestSuperObject implements TestInterface
public interface TestInterface
public class TestSuperObject
public class TestObject3 extends TestSuperObject3
public class TestSuperObject3 implements TestInterface

所以基本上,有没有办法隐藏这些信息或以某种方式丢失类型信息?我不问,因为我有这样做的理由,而是想知道并在未来警惕它,如果它是可能的。另外,我只是觉得它很有趣。

【问题讨论】:

  • 并非如此。你只能通过让instanceof 返回一个看起来错误的值来“欺骗”你的直觉。例如,让o 的类型为TestObject,但由不同的类加载器加载。
  • +1。但是instanceof 运算符的工作方式;你没有机会。
  • 请注意,所有的转换只会改变 variable 或 field 的类型。它从不以任何方式更改指向的对象。 (基本类型的转换略有不同,但不与 instanceof 交互)。
  • 转换原始类型有何不同?
  • @Jeff:将 1234 转换为 byte 确实返回不同的值。将其转换回 int 不会导致 1234。

标签: java casting polymorphism instanceof


【解决方案1】:

您可能会将自己与 instanceof 混淆,但不会与 JVM 混淆。

  • 同名但在不同包中的类是不一样的。这意味着你可以做到

    // in one class
    ClassA classA = new ClassA(); // package1.ClassA
    another.test(classA);
    
    // calls in another class
    public void test(Object o) {
       if (o instanceof ClassA) // package2.ClassA => false 
    
  • 使用不同的类加载器,包和o.getClass().getName() 是相同的,但由于类加载器不同,instanceof 返回 false。

  • 对象是 null 并且 null instanceof ClassB 始终为 false,即使 null 可以分配给任何引用类型。

【讨论】:

  • 最后一个问题浮现在脑海:它甚至会看穿泛型吗?还是泛型本质上没有类型?
  • 泛型主要是编译时特性,instanceof 只检查运行时引用的对象。出于这个原因,如果 T 是泛型,则不能使用 o instanceof T。
【解决方案2】:

所以基本上,有什么方法可以隐藏这些信息或以某种方式丢失类型信息?

不,这是不可能的。

每个对象都有一个真实的类型,Java 的强+静态类型系统使得不可能改变一个对象的类型,或者假装它的实际类型与实际不同。


(假设有可能陷入本机代码并颠覆 Java 类型系统,但这样做的后果可能非常糟糕......crash-the-JVM bad。)

【讨论】:

【解决方案3】:

您可以通过混淆器运行代码。但这基本上是一个重命名。 TestObject 可以重命名为例如A,但instanceof A 仍然返回正确的结果。

顺便说一句:给你的类命名 *Object 是个坏主意(在面向对象的语言中)。

【讨论】:

    【解决方案4】:

    这取决于 OP 真正想要什么,但 this 可能会这样做。

    基本上我将课程设为私有。这意味着任何object instanceof Class 代码都不会编译(在私有类的范围之外)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-15
      相关资源
      最近更新 更多