无限递归的构造器和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 andSettings\mz50947\workspace\TestProject\src>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 andSettings\mz50947\workspace\TestProject\src>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 andSettings\mz50947\workspace\TestProject\src>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 andSettings\mz50947\workspace\TestProject\src>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 andSettings\mz50947\workspace\TestProject\src>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:\java\samples>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:\java\samples>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

}

无限递归的构造器和javap使用指南的更多相关文章

  1. 无限“递归”的python程序

    如果一个函数直接或者间接调用了自己,那么就形成了递归(recursion),比如斐波那契数列的一个实现 def fib(n): if n <= 2: return 1 else: return ...

  2. 【整理】iview Tree数据格式问题,无限递归树处理数据

    iview Tree数据格式问题,无限递归树处理数据 https://juejin.im/post/5b51a8a4e51d455d6825be20

  3. -java转json hibernate懒加载造成的无限递归问题

    1.在判断到底是谁维护关联关系时,可以通过查看外键,哪个实体类定义了外键,哪个类就负责维护关联关系. JoinColumn(name="pid") 2. 在保存数据时,总是先保存的 ...

  4. jackson java转json hibernate懒加载造成的无限递归问题

    @JsonIgnore @JsonFilter @JsonBackReference @JsonManagedReference @JsonIgnoreProperties jackson中的@Jso ...

  5. hibernate无限递归问题

    项目异常如下: 2018-01-26 17:12:38.162 WARN 3128 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionReso ...

  6. JPA一对多循环引用的解决&&JackSon无限递归问题

    说是解决,其实不是很完美的解决的,写出来只是想记录一下这个问题或者看一下有没有哪位仁兄会的,能否知道一二. 下面说说出现问题: 问题是这样的,当我查询一个一对多的实体的时候,工具直接就爆了,差不多我就 ...

  7. C# .NetCore简单实现无限递归的功能

    1:在实际开发中,我们会经常使用到无限递归的情况,如菜单,父子级等的情况 2:Code 1 using System; 2 using System.Collections.Generic; 3 us ...

  8. vue 无限递归级联组件实现方案

    最终组件效果图: 无限级联组件实现思想: 在这里有一个很重要的地方就是前端组件如何与后端匹配方法协调好,无限级联很好实现,但是如何让服务器端可以成功的匹配到条件是一个问题,在这里我借鉴了html元素的 ...

  9. SqlServer与Linq 无限递归目录树且输出层级

    ALTER VIEW [dbo].[view_TreeLevel] AS WITH cte AS ( SELECT a.ModuleID , a.Module_Name , a.Module_Desc ...

随机推荐

  1. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.1

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

  2. [置顶] 教你如何搭建RobotFramework环境

    看到这篇文章的朋友,相信已经知道RobotFramework是干什么的了,我这里就不再赘述了. 搭建步骤: 1. 下载安装Python,下载地址http://www.python.org/getit/ ...

  3. 企业OA面临的问题,以及解决问题的推荐

          现在的企业不管大小都趋于软件话,而办公用的OA软件更是成为了企业中不可获取的一环,一个好的软件能让企业发展的更加顺利,而一个不合适的软件可能让公司哀声怨道反而起了反作用!       OA ...

  4. Python 自动化脚本学习(三)

    函数 例子 def hello(): print("hello" + "world"); 有参数的函数 def hello(name): print(" ...

  5. Js 中常用方法

    一.获取唯一值(2014-12-23) function newGuid() { var guid = ""; var n = (((1 + Math.random()) * 0x ...

  6. 对于IE6及以下版本的处

    判断IE6 CSS 通过判断浏览器类型而加载不同的css样式 所有的IE都起作用: <!--[if IE]> <link rel="stylesheet" typ ...

  7. jquery .net 无刷新多文件上传

    Uploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示.不过官方提供的实例时php版本的,本文将详细介绍Uploadify在Aspnet中的使用,您也可以点击下面的链接进行演示 ...

  8. 《JavaScript 闯关记》之表达式和运算符

    表达式 表达式是由数字.运算符.数字分组符号(如括号).自由变量和约束变量等以能求得数值的有意义排列方法所得的组合.JavaScript 表达式主要有以下几种形式: 原始表达式:常量.变量.保留字. ...

  9. c# 面相对象1-概括

    面向对象和面向过程的区别 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了.  面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为 ...

  10. [转]C++实现系统服务暂停、停止、启动

    /* 名称:系统服务管理 语言:C++ 介绍:对Windows系统服务的状态获取,服务暂停,开启,停止操作代码 */ void CStartServiceDlg::OnBnClickedButton1 ...