【问题标题】:Will new instance of JVM or reflection help in this case在这种情况下,新的 JVM 实例或反射是否有帮助
【发布时间】:2012-07-20 18:00:05
【问题描述】:

我之前发布过一个问题,但没有明确的解决方案

How to prevent JFrame from closing.

所以我发布一个 SSCCE 可能有助于更好地理解所面临的问题

package myApp;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JFrame;

import App2.Applic2;

public class MYApp {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String arg[]){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setTitle("Application frame 1");
        f.setSize(200,200);
        f.setVisible(true);
        Class cls = Applic2.class;
        Object[] actuals = { new String[] { "" } };


        Method m = null;
        try {
            m=cls.getMethod("main", new Class[] { String[].class } );
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            try {
                m.invoke(null,actuals);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

}

第二个包

package App2;

import javax.swing.JFrame;

public class Applic2  {

    @SuppressWarnings("unused")
    public static void main(String args[]){

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(200,200);
        f.setVisible(true);
        f.setTitle("This needs not to be changed");
        NewFrame3 Frame3 = new  NewFrame3();
    }

}

App2 包的第二类。

package App2;

import javax.swing.JFrame;

public class NewFrame3 {

    public NewFrame3(){

        JFrame f = new JFrame();
            f.setTitle("f3");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setSize(200,200);
            f.setLocation(200, 200);
            f.setVisible(true);
    }

}

MYAPP 调用Applic2 的实例,该实例进一步调用NewFrame3 的实例。就像我们可以看到如果我关闭 'NewFrame3' 的实例或 Applic2 的实例,整个程序关闭(由于 EXIT_ON_CLOSE)语句。

我想要一个解决方案,其中 MYAPP 不应该在关闭 Applic2NewFrame3 时关闭。

我无法对 APPlic2 或 NewFrame3 进行任何更改。通过反射如果我们尝试将EXIT_ON_CLOSE 转换为DISPOSE_ON_CLOSE 当我们没有扩展类JFrames 时,我们如何访问这些框架及其setDefaultCloseOperation()

在提到的另一个解决方案中,应该创建一个新的JVM 实例,并且应该在这个新的JVM 实例上的新进程中执行Applic2。但后来我遇到了 runtime.exec 将 Java 命令作为输入,而不是像 method.invoke() 这样的 Java 语句。

我可以通过加载 Applic2 的加载器访问 Applic2 我只能访问内存中 Applic2 的类文件,所以我无法使用 jar 在 runtime.exec() 中运行。现在该如何解决?

将这些语句添加到 MYApp 类可确保在单击框架的关闭按钮时没有任何反应,但情况似乎并非如此

Frame[] f2 = JFrame.getFrames();

            for(Frame fx: f2){
                System.out.println(fx.getTitle());
                fx.addWindowListener(new WindowAdapter(){
                      public void windowClosing(WindowEvent we){


                      }
                      });

并且此代码需要添加到实例化的最后一帧,否则它会返回所有帧。即,如果将此帧添加到 JFrame3 类,则返回所有实例化的帧如果添加到 MyApp,则返回 MyApp 中的 JFrame,如果添加了 Applic2,则返回在 MYApp 和 Applic2 中实例化的帧。为什么会有这种行为??

【问题讨论】:

    标签: java reflection jvm jframe classloader


    【解决方案1】:

    您可以使用JFrame.getFrames(),它返回一个Frame 的数组(您也可以getWindows() 获得在当前应用程序上下文中创建的那些窗口的低级别列表)。

    然后,您需要遍历,检查每一帧,看看它是否符合您的要求。之后,您不需要反射,您可以直接访问框架

    与其他 JVM 通信的唯一方法是通过套接字通信(例如 RMI)。

    示例更新

    Frame[] listOfFrames = JFrame.getFrames();
    for (Frame : listOfFrames) {
      if (frame instanceof JFrame) {
    
          JFrame aFrame = (JFrame)frame;
    
      }
    }
    

    【讨论】:

    • +1 为您的答案此解决方案似乎很有帮助,让我实施它并在此处发布答案以供您参考。但是您可以建议如何使用新的 JVM 实例以其他方式做到这一点。
    • 其他JVM是什么意思?你想和它交谈(跨进程通信)还是执行它??
    • 是的!跨进程通信。执行应用程序的新进程
    • 但 getFrames() 返回 awt 帧以及如何更改这些帧的 DefaultCloseOperation(awt 帧没有任何此类方法)
    • JFrame 是从 java.awt.Frame 扩展而来的,你应该检查该框架是否是 JFrame 的一个实例,然后进行转换
    【解决方案2】:

    跨进程通信不是一件简单的事情。基本上,您要与之交谈的每个进程都需要有一个ServerSocket,它可以接受传入的请求。如果你想执行双向通信,每个进程都需要有自己的ServerSocket,这将允许任何进程启动通信。

    这会引发端口号等问题,但您实际上可以通过组播来解决这个问题(基本上,“大家好,我在这里,来和我说话”),它可以用来确定谁有空与否 - 以 Broadcasting to Multiple Recipients 为例。

    所以。准备好后,您将在其端口上打开与相关进程 (localhost/127.0.0.1) 的套接字连接并开始聊天。

    现在。我看到你所描述的问题是,为了让它运行,你需要某种可以创建服务器套接字然后执行现有程序的启动器(因为你已经已经描述),这就提出了为什么?如果您的唯一目标是让这些帧停止关闭您的应用程序,只需在新的 JVM 中启动程序即可实现该目标。显然,如果您仍然需要他们提供更多信息,那么这是所有辛勤工作的合理借口。

    现在,好消息是,您可以跨套接字序列化对象(也就是说,您可以通过套接字连接发送 Java 对象),请查看Discover the secrets of the Java Serialization API 了解更多信息。

    现在,如果这还没有吓到你,请查看All About Sockets 了解更多信息。

    最后,“如何”执行新 JVM 的大问题,查看 Java ProcessBuilder,它实际上描述了一种执行新 JVM 的方法!!

    【讨论】:

      【解决方案3】:

      所以在 MadProgrammer amd mKorbel 提供的帮助下完成了解决方案,这里是更新的 MYApp 类

      package myApp;
      
      import java.awt.Frame;
      import java.awt.Window;
      import java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
      import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;
      
      import javax.swing.JFrame;
      
      import App2.Applic2;
      
      public class MYApp {
      
          @SuppressWarnings({ "unchecked", "rawtypes" })
          public static void main(String arg[]){
              JFrame f = new JFrame();
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              f.setTitle("Application frame 1");
              f.setSize(200,200);
              f.setVisible(true);
              Class cls = Applic2.class;
              Object[] actuals = { new String[] { "" } };
      
      
      
      
              Method m = null;
              try {
                  m=cls.getMethod("main", new Class[] { String[].class } );
      
      
                  Method[] m1  =Frame.class.getDeclaredMethods();
      
      
      
      
      
      
      
              } catch (NoSuchMethodException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              } catch (SecurityException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
                  try {
                      m.invoke(null,actuals);
                  } catch (IllegalAccessException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  } catch (IllegalArgumentException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  } catch (InvocationTargetException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
      
      
                  Frame[] f2 = JFrame.getFrames();
                  //  Window[] f23=  JFrame.getFrames();
      
                      for(Frame fx: f2){
                          System.out.println(fx.getTitle());
                          //  fx.setVisible(false);
      
                            if (fx instanceof JFrame) {
      
                                JFrame aFrame = (JFrame)fx;
                                aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      
                            }
                          }
      
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-15
        • 1970-01-01
        • 1970-01-01
        • 2011-08-24
        • 1970-01-01
        • 1970-01-01
        • 2021-07-10
        • 1970-01-01
        相关资源
        最近更新 更多