构造函数和类的奇怪行为。应用程序在Constructor上挂起`forever`

时间:2012-07-30 17:06:34

标签: java

更新注意:调试后,我问了另一个问题:Class Constructor fails throwing Exception on Class Loading

首先,我想不出一个更好的名称,我的问题就是: WEIRD BEAVAVIOR 。如果你想到更合适的东西,请编辑。

现在,我将尝试尽可能地简化这一点,遗憾的是我无法泄露给我提出问题的代码。

我有 A类 B类 Z类

A类和B类非常相似,两者都有一个具有相同参数的构造函数,每个都有一个调用SOAP Web服务的方法,一个用于执行操作A ,另一个做操作B

现在,问题是什么? Class Z实例化Class AClass B,然后someMethod()调用对象的方法分别执行操作A和B.

出于某种原因,似乎没有调用ClassB的构造函数,并且从调用构造函数的那一刻起就没有System.out.println()打印任何内容,程序挂起永远,我的意思是,它永远不会抛出异常或继续做任何事情。看看如何在A类和B类的第一行打印一个标志,它不会打印出ClassB。

我做了什么

  1. ClassZ上我更改了A类和B类的顺序 - > 结果:它挂在同一个地方,现在甚至连A类构造函数和方法都没有被调用
  2. 在ClassB上,我评论了所有内容,并开始逐个对每条指令进行解除评论,从构造函数开始,然后使用MethodB,这里是我被卡住并来到这里的地方,因为我找到的对我来说没有任何意义在我的工作场所也没有人。 结果 - >

    2.1 如果我评论methodB上的所有内容,但最后返回false并保持构造函数不变,则会继续正常执行

    2.2 如果我对2.1上的所有内容以及methodB中从WebService调用operationB的部分进行取消注释并检查其结果,则会正常继续执行

    2.3 如果我再发表评论,当我开始使用数据库时,它会挂起。

  3. 我检查了数据库的连接数,它仍有许多可用的

  4. 让我困惑的是,如果它与数据库相关,为什么它会像构造函数那样挂起?

    一般事实

    1. 我正在使用JDBC连接到MySQL数据库
    2. 我拥有try {} catch(Exception e){}的所有内容,我在e上打印所有内容,但它不会打印任何内容,也不会抛出任何异常。
    3. 这是他们的样子:

      CLASS A:

      // ClassA.java
      
      public ClassA{
          private UserInfo user;
          private WebServiceADelegate port;
          private Connection conn;
      
          public ClassA (UserInfo user, Connection conn) throws Exception {
              System.out.println("CLASS A CONSTRUCTOR");
              this.user = user;
              this.conn = conn;
              this.port = new WebServiceAService().getForwardingPort();
          }
      
          public boolean methodA(List<String> list){
              // Check some stuff on database using this.conn
              // Get the values to invoke SOAP service using this.conn
              status = port.operationA(values);
              if(status > 0)
                  return true;
              return false;
          }
      
      }
      

      CLASS B:

      // ClassB.java
      
      public ClassB{
          private UserInfo user;
          private WebServiceBDelegate port;
          private Connection conn;
      
          public ClassB (UserInfo user, Connection conn) throws Exception {
              System.out.println("CLASS B CONSTRUCTOR");
              this.user = user;
              this.conn = conn;
              this.port = new WebServiceBService().getForwardingPort();
          }
      
          public boolean methodB(List<String> list){
              // Check some stuff on database using this.conn
              // Get the values to invoke SOAP service using this.conn
              status = port.operationB(values);
              if(status > 0)
                  return true;
              return false;
          }
      
      }
      

      CLASS Z:

      // ClassZ.java
      
      public ClassZ{
          private Connection conn;
          // ...        
          // ...
          public boolean someMethod (){
              System.out.println("GONNA CALL CONSTRUCTOR ClassA");
              ClassA webservice = new ClassA(user, conn);
              System.out.println("GONNA CALL METHOD FROM ClassA");
              if (!webservice.methodA(list) ){
                  return false;
              }
      
              System.out.println("GONNA CALL CONSTRUCTOR ClassB");
              ClassB webservice2 = new ClassB(user, conn);
              System.out.println("GONNA CALL METHOD FROM ClassB");
              if (!webservice2.methodB(list) ){
                  return false;
              }
              return true;
          }
      }
      

      它挂起的最后一个输出总是:"GONNA CALL CONSTRUCTOR ClassB"

      谢谢!

      更新

      我调试了我的应用并修复了它,但它仍然很奇怪。明天我会详细说明是否有人可以告诉我发生了什么。

      长话短说:我在ClassB上导入javax.persistence.NoResultException,而在methodB里面我正在做try{}catch(NoResultException nre){ //...} ...在某些情况下,当JVM在调用Constructor之前调用ClassLoader时,它正在抛出前面提到的异常和从那一点开始的行为很奇怪,执行结束了。

      有涉及的线程,这就是为什么我挂起,它没有挂起,线程结束,我没有注意到。

      另外一个注意事项:ClassB 使用JPA,导入以及它的捕获不正确,一些非常古老的代码设法生存。但是我认为这不能证明错误。

      我问了另一个问题,一个是调试结果。您可以在Class Constructor fails throwing Exception on Class Loading

      中查看

2 个答案:

答案 0 :(得分:1)

嗯,很难说提供的信息,但有些暗示我会检查:

  1. 首先使用调试器并将转换为构造函数,以确定它挂起的位置。知道它是构造函数调用是不够的。走进去。
  2. 网络服务电话很可能会挂起。所以你称之为webmethod并且它不会永远返回。所以你的程序永远挂起。
  3. 挂起可以是任何东西,但是当你处理数据库时,挂起很可能来自数据库锁。当您未正确提交/回滚时,可以在此处轻松生成死锁。
  4. 一些疯狂的猜测,但也许有帮助...

答案 1 :(得分:0)

  1. 应用程序没有永远挂起。这段代码在另一个线程中运行,所以当它的执行失败时,它就完成了,没有我注意到。
  2. 问题实际上是在调用构造函数时。我的类路径中没有类javax.persistence.NoResultException,因此在创建实例时以及检查依赖项时,JVM ClassLoader无法找到它。
  3. 找出问题甚至很难调试,因为我有很多 try {} catch(Exception e){}但是即使JVM ClassLoader的ClassLoader.loadClass()说它抛出异常ClassLoader.loadClass() signature ispublic Class<?> loadClass(String name) throws ClassNotFoundException),它也是实际上抛出一个NoClassDefFoundError,其中不会扩展异常,它会延伸Throwable,因此我的catch(Exception e){}没有捕获,我必须catch(Throwable t){}
  4. 为什么它会抛出不同的东西,这是因为Java的内部类加载如何工作。它比调用loadClass要复杂一些。它必须加载,链接,验证和初始化它。在某些时候,它应该在调用NoClassDefFoundError时抛出defineClass()。有关详情,请访问on the Execution part of the JLS
  5. 有关正在进行的更详细的回答,请在调试后检查我关于此问题的其他问题以及接受的答案Class Constructor fails throwing Exception on Class Loading