• 无限递归的构造器和javap使用指南


    无限递归的构造器和javap使用指南

    public class ConstructorRecursion {

          ConstructorRecursion rc;

          {

                rc = newConstructorRecursion();

          }

          public ConstructorRecursion(){

                System.out.println("noparameter constructor");

          }

          public static void main(String[] args){

                ConstructorRecursion rc = new ConstructorRecursion();

          }

    }

    Exceptionin thread "main" java.lang.StackOverflowError

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

          at ConstructorRecursion.<init>(ConstructorRecursion.java:5)

    表面上看,上面程序没有任何问题,ConstructorRecursion类的构造器中没有任何代码,只是单纯一句输出。但不要忘记了,不管是定义实例变量时指定的初始值,还是在非静态初始化块中执行的初始化操作,最终都将提取到构造器中执行。因为上面代码递归调用了ConstructorRecursion类的狗仔去哦,所以抛出了StackOverflowError错误。

    这个程序给出的教训是:无论如何不要导致构造器产生递归调用。也就是说,应该:

    尽量不要在定义实例变量时指定实例变量的值为当前类的实例;

    尽量不要初始化块中创建当前类的实例;

    尽量不要在构造器内调用本构造器创建Java对象;

    C:Documents andSettingsmz50947workspaceTestProjectsrc>javap ConstructorRe

    ursion

    Compiled from"ConstructorRecursion.java"

    public classConstructorRecursion extends java.lang.Object{

        ConstructorRecursion rc;

        public ConstructorRecursion();

        public static voidmain(java.lang.String[]);

    }

    使用JAVAP可以查看java编译器生成的字节码,通过比较字节码和源代码,可以发现很多的问题。

    C:Documents andSettingsmz50947workspaceTestProjectsrc>javac -g Constructor

    Recursion.java

    08/08/2013  02:50 PM               645 ConstructorRecursion.class

    08/08/2013  02:34 PM               304 ConstructorRecursion.java

    不带参数的javap将打印类的public信息,包括成员和方法。

    C:Documents andSettingsmz50947workspaceTestProjectsrc>javap -c Constructor

    Recursion

    Compiled from"ConstructorRecursion.java"

    public classConstructorRecursion extends java.lang.Object{

    ConstructorRecursionrc;

    publicConstructorRecursion();

      Code:

       0:  aload_0

       1:  invokespecial   #1; //Methodjava/lang/Object."<init>":()V

       4:  aload_0

       5:  new     #2; //classConstructorRecursion

       8:  dup

       9:  invokespecial   #3; //Method"<init>":()V

       12: putfield        #4; //Fieldrc:LConstructorRecursion;

       15: getstatic       #5; //Fieldjava/lang/System.out:Ljava/io/PrintStream;

       18: ldc     #6; //String no parameterconstructor

       20: invokevirtual   #7; //Methodjava/io/PrintStream.println:(Ljava/lang/Str

    ing;)V

       23: return

    public static voidmain(java.lang.String[]);

      Code:

       0:  new     #2; //classConstructorRecursion

       3:  dup

       4:   invokespecial  #3; //Method "<init>":()V

       7:  astore_1

       8:  return

    }

    C:Documents andSettingsmz50947workspaceTestProjectsrc>javap -l Constructor

    Recursion

    Compiled from"ConstructorRecursion.java"

    public classConstructorRecursion extends java.lang.Object{

    ConstructorRecursionrc;

    publicConstructorRecursion();

      LineNumberTable:

       line 7: 0

       line 5: 4

       line 8: 15

       line 9: 23

      LocalVariableTable:

       Start Length  Slot  Name  Signature

       0     24      0    this      LConstructorRecursion;

    public static voidmain(java.lang.String[]);

      LineNumberTable:

       line 11: 0

       line 12: 8

      LocalVariableTable:

       Start Length  Slot  Name  Signature

       0     9      0    args      [Ljava/lang/String;

       8     1      1    rc      LConstructorRecursion;

    }

    C:Documents andSettingsmz50947workspaceTestProjectsrc>javap -c Constructor

    Recursion

    Compiled from"ConstructorRecursion.java"

    public classConstructorRecursion extends java.lang.Object{

    ConstructorRecursionrc;

    public ConstructorRecursion();

      Code:

       0:  aload_0

       1:  invokespecial   #1; //Methodjava/lang/Object."<init>":()V

       4:  aload_0

       5:  new     #2; //classConstructorRecursion

       8:  dup

       9:  invokespecial   #3; //Method"<init>":()V

       12: putfield        #4; //Fieldrc:LConstructorRecursion;

       15: getstatic       #5; //Fieldjava/lang/System.out:Ljava/io/PrintStream;

       18: ldc     #6; //String no parameterconstructor

       20: invokevirtual   #7; //Methodjava/io/PrintStream.println:(Ljava/lang/Str

    ing;)V

       23: return

    public static voidmain(java.lang.String[]);

      Code:

       0:  new     #2; //classConstructorRecursion

       3:  dup

       4:  invokespecial   #3; //Method"<init>":()V

       7:  astore_1

       8:  return

    }

    The javap command iscalled the Java “disassembler”because it takes apart class files andtells you what’s inside them. You won’t use this command often, but using it tofind out how a particular Java statement works is fun, sometimes. You can alsouse it to find out what methods are available for a class if you don’t have thesource code that was used to create the class.

    Here is the general format:

    javapfilename [options]

    The following is typical of the information you getwhen you run the javap command:

    C:javasamples>javapHelloApp

    Compiledfrom "HelloApp.java"

    publicclass HelloApp extends java.lang.Object{

        public HelloApp();

        public static voidmain(java.lang.String[]);

    }

    As you can see, the javap command indicates that the HelloApp class was compiled from the HelloApp.java file and that it consists of a HelloApppublic class and a mainpublic method.

    You may want to use two options with the javap command. If you use the -c option, the javap command displays the actual Java bytecodes createdby the compiler for the class. (Java bytecode is the executable programcompiled from your Java source file.)

    And if you use the -verbose option, the bytecodes — plus a ton of otherfascinating information about the innards of the class — are displayed. Here’sthe -c output for aclass named HelloApp:

    C:javasamples>javapHelloApp -c

    Compiledfrom "HelloApp.java"

    publicclass HelloApp extends java.lang.Object{

    publicHelloApp();

      Code:

       0:  aload_0

       1:  invokespecial   #1; //Method

      java/lang/Object."<init>":()V

       4:  return

    publicstatic void main(java.lang.String[]);

      Code:

       0:  getstatic       #2; //Field

       java/lang/System.out:Ljava/io/PrintStream;

       3:  ldc     #3; //String Hello, World!

       5:  invokevirtual   #4; //Method

       java/io/PrintStream.println:(Ljava/lang/String;)V

       8:  return

    }

  • 相关阅读:
    提交按钮变灰
    解析spring启动加载dubbo过程
    shiro的SecurityUtis
    spring集成shiro登陆流程(下)
    spring集成shiro登陆流程(上)
    shiro的DelegatingFilterProxy怎么找到ShiroFilterFactoryBean
    sql多表关联
    android常用控件
    android控件之EditText
    浅议iOS网络数据解析
  • 原文地址:https://www.cnblogs.com/riskyer/p/3246871.html
Copyright © 2020-2023  润新知