无限递归的构造器和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. Live555类结构

    Medium live555几乎所有的处理单元都继承自Medium类:该类抽象了基本的接口,包括环境,task和媒体名和媒体查找函数(lookupByName)以及一些辅助函数.也包括返回当前的环境类 ...

  2. 【剑指offer】面试题20:顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1     2  3   4 5    6   7   8 9   10 11 12 13 14 15 ...

  3. 玩转iOS开发 - JSON 和 Xml 数据解析

    前言 Json 和xml是网络开发中经常使用的数据格式,JSON轻量级.xml相对较复杂.所以如今用JSON的比例很大.基本上从server获取的返回数据都是JSON格式的,作为iOS开发人员,解析J ...

  4. idea maven 无法加载已经安装的模块

    新建了一下maven项目,下面新建了一个模块,某一个模块clean install之后,别的模块虽然使用dependency标签引入了,但是仍然无法使用, 这个时候,应该重新建立一个项目,将原有项目的 ...

  5. ASP.NET Signalr 2.0 实现一个简单的聊天室

    学习了一下SignalR 2.0,http://www.asp.net/signalr 文章写的很详细,如果头疼英文,还可以机翻成中文,虽然不是很准确,大概还是容易看明白. 理论要结合实践,自己动手做 ...

  6. android如何调用显示和隐藏系统默认的输入法(一)

    1.调用显示系统默认的输入法 方法一. InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_MET ...

  7. 一个SQL 建表格式

    CREATE TABLE [dbo].[SysSample]([Id] [varchar](50) NOT NULL,[Name] [varchar](50) NULL,[Age] [int] NUL ...

  8. 封装一些数据库SQLCipher的方法(增、删、改、查)

    上一篇随笔只是简单的说了一下使用SQLCipher框架,介绍的比较笼统,可能看一遍之后更加蒙圈了,为了更好的使用这个数据库,整理了我在公司项目的需要用的方法,包括创建表,插入数据,更新数据,搜索查询数 ...

  9. PHP基础之 file_get_contents() 函数

    定义和用法 file_get_contents() 函数把整个文件读入一个字符串中. 和 file() 一样,不同的是 file_get_contents() 把文件读入一个字符串. file_get ...

  10. linux学习笔记之文件结构和函数

    本文参考<UNIX环境高级编程> 一.基础介绍. 1:文件的构成. 1,首先声明,这里的文件和目录,表示普通的文件和目录.不确定是否可以应用到:设备,管道等特殊形式的文件(UNIX把它们也 ...