无限递归的构造器和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 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使用指南的更多相关文章
- 无限“递归”的python程序
如果一个函数直接或者间接调用了自己,那么就形成了递归(recursion),比如斐波那契数列的一个实现 def fib(n): if n <= 2: return 1 else: return ...
- 【整理】iview Tree数据格式问题,无限递归树处理数据
iview Tree数据格式问题,无限递归树处理数据 https://juejin.im/post/5b51a8a4e51d455d6825be20
- -java转json hibernate懒加载造成的无限递归问题
1.在判断到底是谁维护关联关系时,可以通过查看外键,哪个实体类定义了外键,哪个类就负责维护关联关系. JoinColumn(name="pid") 2. 在保存数据时,总是先保存的 ...
- jackson java转json hibernate懒加载造成的无限递归问题
@JsonIgnore @JsonFilter @JsonBackReference @JsonManagedReference @JsonIgnoreProperties jackson中的@Jso ...
- hibernate无限递归问题
项目异常如下: 2018-01-26 17:12:38.162 WARN 3128 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionReso ...
- JPA一对多循环引用的解决&&JackSon无限递归问题
说是解决,其实不是很完美的解决的,写出来只是想记录一下这个问题或者看一下有没有哪位仁兄会的,能否知道一二. 下面说说出现问题: 问题是这样的,当我查询一个一对多的实体的时候,工具直接就爆了,差不多我就 ...
- C# .NetCore简单实现无限递归的功能
1:在实际开发中,我们会经常使用到无限递归的情况,如菜单,父子级等的情况 2:Code 1 using System; 2 using System.Collections.Generic; 3 us ...
- vue 无限递归级联组件实现方案
最终组件效果图: 无限级联组件实现思想: 在这里有一个很重要的地方就是前端组件如何与后端匹配方法协调好,无限级联很好实现,但是如何让服务器端可以成功的匹配到条件是一个问题,在这里我借鉴了html元素的 ...
- SqlServer与Linq 无限递归目录树且输出层级
ALTER VIEW [dbo].[view_TreeLevel] AS WITH cte AS ( SELECT a.ModuleID , a.Module_Name , a.Module_Desc ...
随机推荐
- logstash 解析mysql slow log
# User@Host: zjzc_app[zjzc_app] @ [10.252.148.16xx] Id: 6043127 # Query_time: 2.581184 Lock_time: 0. ...
- 开源欣赏wordpress之用户新增user-new.php
require_once( dirname( __FILE__ ) . '/admin.php' ); 引入根文件. if ( is_multisite() ) { if ( ! current_us ...
- Liferay门户网站portal
转自:http://www.oschina.net/p/liferay+portal Liferay 是一个完整的门户解决方案,基于J2EE的应用,使用了EJB以及JMS等技术,前台界面部分使用Str ...
- BFS visit tree
There are two ways to conduct BFS on tree. Solution 1 -- Given level Use recursion to find given lev ...
- 三十三、Java图形化界面设计——布局管理器之null布局(空布局)
摘自http://blog.csdn.net/liujun13579/article/details/7774267 三十三.Java图形化界面设计--布局管理器之null布局(空布局) 一般容器都有 ...
- Calculation(dfs+状压dp)
Problem 1608 - Calculation Time Limit: 500MS Memory Limit: 65536KB Total Submit: 311 Accepted: ...
- Keepalived+Lvs+Mysql主主复制
一简单介绍 Keepalived+lvs+mysql主主复制是比較经常使用的一种Mysql高可用方案,当中lvs 提供读负载均衡,Keepalived通过虚拟vip漂移实现故障自己主动转移,而Mysq ...
- 编解码学习笔记(十):Ogg系列
Ogg是一个自由且开放标准的容器格式,由Xiph.Org 基金会所维护.Ogg格式并不受到软件专利的限制,并设计用于有效率地串流媒体和处理高质量的数字多媒体. Ogg意指一种文件格式,能够纳入各式各样 ...
- php接口数据加密、解密、验证签名代码实例
php接口数据加密.解密.验证签名 代码非常easy,这里就不多废话了,直接奉上代码 <?php /** * 数据加密.解密.验证签名 * @edit http://www.lai18.com ...
- Linux shell 的 test 命令用法详解
基本格式:test expression expression为test命令构造的表达式.这里expression是test命令可以理解的任何有效表达式,该简化格式将是读者可能会踫见的最常用格式返回值 ...