论坛首页 综合技术论坛

高手问答:实战Java虚拟机——JVM故障诊断与性能优化--获奖名单公布

浏览 15123 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2015-05-08  
关于substring的解读,第一遍没有看太明白,自己编程能力还需要加强。我会不断的读,研究,知道自己明白为什么。

不过关于final的使用,我很好奇,因为我对于final的使用非常的短见,
Thread thread = new Thread(new Runnable() {
						@Override
						public void run() {
							ConnectionManager.requestFrontClient(msg);
						}
					});

之前有这样一串代码,在以前,我不知道怎么把msg的参数传递到线程内部,然而请教一个同事之后,他告诉我在外部对msg加上final修饰后,就可以使用了,final保证了在一个线程内部,msg不被其他外部资源修改,但是我没有太好的理解,还没有找到比较充分的资料说明,在这里有机会请教一下您,还望您不辞辛劳作答,谢谢您。
0 请登录后投票
   发表时间:2015-05-08  
qing_gee 写道
String str1 = new String("123");
String str2 = new String("123");

System.out.println(str1.intern() == str2.intern());
对于两个字符串的常量值引用比较,我第一次没有认真看,就认为是不相等的,再重新看作者的解释就恍然大悟了,的确,比较两个在常量池中的引用,自然应该相等,不然就没有任何意义了。

不过我觉得作者对于多线程导致OOM的解答不够全面,因为之前我曾经在我的交易平台中就遇到了这个问题,通过设置-Xmx512m、-Xmx1g -Xss128k显然不是正确的解决办法,在很多时候,发生内存溢出时因为代码逻辑或者代码隐藏有漏洞,而正是这些隐藏漏洞导致出现了OOM,如果这样笼统让大家更改参数去避免bug,可能会误导大家。

小小建议,我只是站在自己的角度思考问题,如有不当,还请谅解。

另外,我想推荐一款IBM的内存溢出分析工具,作者说的两款工具我没有实战过,不过IBM的这款工具的确还是很不错的,是通过Java写的,ftp://public.dhe.ibm.com/software/websphere/appserv/support/tools/HeapAnalyzer/ha456.jar。


感谢你的关注!通过设置-Xmx512m、-Xmx1g -Xss128k 参数的方式 只是为了使得让系统能够支持更多的线程,如果系统本身就有内存泄露。通过参数调整是无济于事的。还是要找到根本原因的。这里只是给出一种参数设置的思路。
感谢你分享的工具。非常不错!
0 请登录后投票
   发表时间:2015-05-08  
qing_gee 写道
关于substring的解读,第一遍没有看太明白,自己编程能力还需要加强。我会不断的读,研究,知道自己明白为什么。

不过关于final的使用,我很好奇,因为我对于final的使用非常的短见,
Thread thread = new Thread(new Runnable() {
						@Override
						public void run() {
							ConnectionManager.requestFrontClient(msg);
						}
					});

之前有这样一串代码,在以前,我不知道怎么把msg的参数传递到线程内部,然而请教一个同事之后,他告诉我在外部对msg加上final修饰后,就可以使用了,final保证了在一个线程内部,msg不被其他外部资源修改,但是我没有太好的理解,还没有找到比较充分的资料说明,在这里有机会请教一下您,还望您不辞辛劳作答,谢谢您。


内部类访问外部类的成员是,必须是final的。final表示常量,是指这个引用不会再改变了(并不表示引用代表的对象不是只读的)。
这么做的原因是,内部类 其实 并没有直接访问外部类的参数。这些参数实际上是在内部类的构造函数中传入的。比如:
public class OuterClass {
    public void test() {
        final String msg = new String("read from other");
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(msg);
            }
        });
    }
}

上面代码的那个匿名内部类的 实际内容 会像这样:
内部类会自动增加 2个 成员变量:
final OuterClass this$0; //表示外部类
private final java.lang.String val$msg; //就是那个参数msg
然后 内部类的构造函数是:
OuterClass$1(OuterClass, java.lang.String);
一看就应该知道 第一个是外部类,第2个就是参数。

所以在内部类方法被调用是,实际上是去拿自己的字段的。此时 ,如果外部类 修改了这个变量,内部类是不知道的。所以,必须是final。

0 请登录后投票
   发表时间:2015-05-09  
billykinggym 写道
qing_gee 写道
String str1 = new String("123");
String str2 = new String("123");

System.out.println(str1.intern() == str2.intern());
对于两个字符串的常量值引用比较,我第一次没有认真看,就认为是不相等的,再重新看作者的解释就恍然大悟了,的确,比较两个在常量池中的引用,自然应该相等,不然就没有任何意义了。

不过我觉得作者对于多线程导致OOM的解答不够全面,因为之前我曾经在我的交易平台中就遇到了这个问题,通过设置-Xmx512m、-Xmx1g -Xss128k显然不是正确的解决办法,在很多时候,发生内存溢出时因为代码逻辑或者代码隐藏有漏洞,而正是这些隐藏漏洞导致出现了OOM,如果这样笼统让大家更改参数去避免bug,可能会误导大家。

小小建议,我只是站在自己的角度思考问题,如有不当,还请谅解。

另外,我想推荐一款IBM的内存溢出分析工具,作者说的两款工具我没有实战过,不过IBM的这款工具的确还是很不错的,是通过Java写的,ftp://public.dhe.ibm.com/software/websphere/appserv/support/tools/HeapAnalyzer/ha456.jar。


感谢你的关注!通过设置-Xmx512m、-Xmx1g -Xss128k 参数的方式 只是为了使得让系统能够支持更多的线程,如果系统本身就有内存泄露。通过参数调整是无济于事的。还是要找到根本原因的。这里只是给出一种参数设置的思路。
感谢你分享的工具。非常不错!


非常感谢你的回复,其实在我没有解决系统本身漏洞的时候,先是加上了-Xmx512m、-Xmx1g -Xss128k去尽量避免内存溢出的问题,防止当前的程序占用过多资源导致其他程序出现内存不足的问题。
0 请登录后投票
   发表时间:2015-05-09  
billykinggym 写道
qing_gee 写道
关于substring的解读,第一遍没有看太明白,自己编程能力还需要加强。我会不断的读,研究,知道自己明白为什么。

不过关于final的使用,我很好奇,因为我对于final的使用非常的短见,
Thread thread = new Thread(new Runnable() {
						@Override
						public void run() {
							ConnectionManager.requestFrontClient(msg);
						}
					});

之前有这样一串代码,在以前,我不知道怎么把msg的参数传递到线程内部,然而请教一个同事之后,他告诉我在外部对msg加上final修饰后,就可以使用了,final保证了在一个线程内部,msg不被其他外部资源修改,但是我没有太好的理解,还没有找到比较充分的资料说明,在这里有机会请教一下您,还望您不辞辛劳作答,谢谢您。


内部类访问外部类的成员是,必须是final的。final表示常量,是指这个引用不会再改变了(并不表示引用代表的对象不是只读的)。
这么做的原因是,内部类 其实 并没有直接访问外部类的参数。这些参数实际上是在内部类的构造函数中传入的。比如:
public class OuterClass {
    public void test() {
        final String msg = new String("read from other");
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(msg);
            }
        });
    }
}

上面代码的那个匿名内部类的 实际内容 会像这样:
内部类会自动增加 2个 成员变量:
final OuterClass this$0; //表示外部类
private final java.lang.String val$msg; //就是那个参数msg
然后 内部类的构造函数是:
OuterClass$1(OuterClass, java.lang.String);
一看就应该知道 第一个是外部类,第2个就是参数。

所以在内部类方法被调用是,实际上是去拿自己的字段的。此时 ,如果外部类 修改了这个变量,内部类是不知道的。所以,必须是final。



非常感谢你的回答,我亲自做出了实验,
class TestFinal$1 extends Thread
{
  TestFinal$1(TestFinal paramTestFinal, String paramString)
  {
  }

  public void run()
  {
    System.out.println(this.val$msg);
  }
}

的确构造参数中有两个参数,如你所说。

不过我还想请教的是,我通过反编译看到了以上内容,却没有看到构造参数内部的内容,但是没有看到如何进行赋值,你能告知办法吗?
0 请登录后投票
   发表时间:2015-05-09  
常用jvm 参数都有哪些?
jvm 的图形化监控工具都有哪些?
0 请登录后投票
   发表时间:2015-05-09  
一般怎么分析  cpu过高和内存过高两种情况??
0 请登录后投票
   发表时间:2015-05-11  
qing_gee 写道
billykinggym 写道
qing_gee 写道
关于substring的解读,第一遍没有看太明白,自己编程能力还需要加强。我会不断的读,研究,知道自己明白为什么。

不过关于final的使用,我很好奇,因为我对于final的使用非常的短见,
Thread thread = new Thread(new Runnable() {
						@Override
						public void run() {
							ConnectionManager.requestFrontClient(msg);
						}
					});

之前有这样一串代码,在以前,我不知道怎么把msg的参数传递到线程内部,然而请教一个同事之后,他告诉我在外部对msg加上final修饰后,就可以使用了,final保证了在一个线程内部,msg不被其他外部资源修改,但是我没有太好的理解,还没有找到比较充分的资料说明,在这里有机会请教一下您,还望您不辞辛劳作答,谢谢您。


内部类访问外部类的成员是,必须是final的。final表示常量,是指这个引用不会再改变了(并不表示引用代表的对象不是只读的)。
这么做的原因是,内部类 其实 并没有直接访问外部类的参数。这些参数实际上是在内部类的构造函数中传入的。比如:
public class OuterClass {
    public void test() {
        final String msg = new String("read from other");
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(msg);
            }
        });
    }
}

上面代码的那个匿名内部类的 实际内容 会像这样:
内部类会自动增加 2个 成员变量:
final OuterClass this$0; //表示外部类
private final java.lang.String val$msg; //就是那个参数msg
然后 内部类的构造函数是:
OuterClass$1(OuterClass, java.lang.String);
一看就应该知道 第一个是外部类,第2个就是参数。

所以在内部类方法被调用是,实际上是去拿自己的字段的。此时 ,如果外部类 修改了这个变量,内部类是不知道的。所以,必须是final。



非常感谢你的回答,我亲自做出了实验,
class TestFinal$1 extends Thread
{
  TestFinal$1(TestFinal paramTestFinal, String paramString)
  {
  }

  public void run()
  {
    System.out.println(this.val$msg);
  }
}

的确构造参数中有两个参数,如你所说。

不过我还想请教的是,我通过反编译看到了以上内容,却没有看到构造参数内部的内容,但是没有看到如何进行赋值,你能告知办法吗?


这个内容可能很多反编译软件都做不了。因为这取决于反编译器的实现。我建议你可以直接使用javap进行反汇编。不过需要阅读字节码。
0 请登录后投票
   发表时间:2015-05-11  
empireghost 写道
常用jvm 参数都有哪些?
jvm 的图形化监控工具都有哪些?


参数太多了。可能就不能一一列举了。比如Xmx Xms Xss等等。好几百个呢。

自带的 jconsole jvisualvm 都不错。商业的有jprofile这些。总之选择性还是挺多的
0 请登录后投票
   发表时间:2015-05-11  
empireghost 写道
一般怎么分析  cpu过高和内存过高两种情况??


cpu过高 在windows上你可以试试 process explorer的工具。可以查看到线程
linux上 可以试试pidstat的工具。

内存过高你指的是内存溢出 或者泄露吗? 你可以dump出内存,使用mat或者 jvisualvm之类的工具查看堆中数据
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics