有没有办法获得对在 java 中调用方法的对象的引用?

Is there any way to get reference to object that called a method in java?

提问人:RORAK 提问时间:7/14/2022 最后编辑:RORAK 更新时间:7/21/2022 访问量:84

问:

我需要某种方法来获取调用某个方法的类的实例。例如,在这个程序中,我想获取名为 method 的实例(此处名为 Jack)。PersonMain.call()

public class Main {
   public static Person p;
   public static void main(String[] args) {
      p = new Person("Jack");
      p.call();
   }
   public static void call() {
      Object caller = Magic.getTrace()[1].getObject(); // This is what I need
      System.out.println(((Person)caller).getName()); // Output: Jack
      Class<?> clazz = Magic.getTrace()[2].getClass(); // This too
      System.out.println(clazz.getName()); // Output: Main
}
public class Person {
   private String name;
   public Person(String _name) {
      name = _name
   }
   public String getName() { return name; }
   public void call() {
      Main.call();
   }
}

那么,有什么方法可以做到这一点吗?这应该是可能的,因为调试器可以使用它。

对于模组:我不想要类的 NAME,而是 INSTANCE...

谢谢!

Java 方法 调用 stack-trace

评论

0赞 Rogue 7/14/2022
获取调用类的实例:no。您可以获取有关它的堆栈跟踪详细信息,但只有在将实际实例传递给调用时才能检索它。但是,在 中,您知道哪个在调用(因为它是关键字)。您也可以在调试器中看到这一点,当在内部时,没有可参考的内容。Person#callPersonMain#callthisMain#callPerson
0赞 RORAK 7/14/2022
@Rogue我不想在这个人的情况下使用它。我正在制作一些锁安全类,其中只有创建锁的对象才能访问它。如果你把这个对象作为一个参数传递,那么绕过它就非常容易了......我可以使用一些安全代码,但这也是不安全的,因为反射是一回事......
0赞 Rogue 7/14/2022
几年前,我创建了一个类似的工具,它并非没有几个缺点。首先,这些检查可以被任何足够熟练的人无效。其次,您的代码可以反编译和重新编译。您仍然可以传递要访问 Lock 的对象,以便它可以在内部检查该对象是否应该获得访问权限,如果它们不这样做,则引发异常。阻止调用本身不会发生,堆栈跟踪检查将非常昂贵。
0赞 Rogue 7/14/2022
如果重新打开问题,有一个合理的解决方案,使用 package-private 和两个单独的类:一个用于在创建后保存,另一个用于指定谁可以访问它。现在,我将添加有关您希望限制访问的实际类的更多详细信息(例如,它们是否在程序的整个生命周期中持续创建,并且是仅针对已知类还是可能用于任何新类)Lock
0赞 RORAK 7/14/2022
@Rogue,可以使用反射访问包私有类吗?

答:

1赞 Stephen C 7/16/2022 #1

没有一种方法不能相对容易地被颠覆。这使得这种安全机制毫无意义。

请注意,使用 可能(已经)可以做一些事情,但这假设您的代码仅从“沙箱”中的代码调用。并且需要在沙盒中禁用各种东西......从反思开始......这对于现代 Java 程序员来说太麻烦了。SecurityManager

基本上,如果你有一个安全机制,需要对你的代码用户强制执行,那么它就需要在运行他们的代码的JVM之外完成。通常,您将在远程服务器上执行检查...您的用户无法干涉。

(“在服务器中执行此操作”方法可能不可行或对您来说是不可接受的。在这种情况下:对不起,但没有真正的解决方案。只有那些给你一种错觉的方法,你已经解决了问题。

你注意到了这一点:

这应该是可能的,因为调试器可以使用它。

对不起,没有。

调试器使用 debug-agent 来访问他们正在调试的 JVM 的状态。不幸的是(或者也许是幸运的,取决于你的观点!)JVM不能在自己身上使用调试代理。这是行不通的。

我的理解是,调试代理代码在执行其操作时会暂停目标 JVM 中的所有线程。当 JVM 尝试“自我调试”时,这包括 JVM 中尝试使用代理的线程。即时死锁。

此外,想要破坏任何基于代理的安全机制的人只需要在启动 JVM 时不附加代理即可。