188bet官网2018

使用初始的GC配置,每三秒发生一次80ms的新生代GC停顿,超过百分之99.9的应用延迟100ms。对我们而言,这个进程很有可能就是我们的应用程序。清晰地了解GC日志和常用的JVM参数对简单调整GC运行很有必要。后面两个结果一个是a指向常量池的“abc”,b指向常量池中的“def”,c是通过a和b相加,两个都是常量池对象;而d是直接等价于“abc”+“def”按照道理说,两个也是常量池对象,为什么两个对象和常量池的“abcdef”比较的结果不一样呢?(关于他们为什么是在常量池就不多说了,上面那一段已经有结果了);我们不管怎么样,首先秒杀掉一句话就是:常量池的String+常量池String结果还在常量池,这句话是不正确的,或者你的测试用例正好是后者,那么你中招了,很多事情只是通过测试也未必能得出非常有效的结果,但是较为全面的测试会让我们得出更多的结论,看看我们两种几乎一摸一样的测试,但是结果竟然是不一样的;简单说结果是前者的对象结果不是在常量池中(记住,常量池中同一个字符串肯定是唯一的),后者的结果肯定在常量池;为什么,不是我说的,是HotspotVM告诉我的,我们做一个简单的小实验,就知道是为什么了,首先将代码修改成这样:publicclassStringTest{???publicstaticvoidmain(String[]args){????Stringa="abc";????Stringb="def";?????Stringc=a+b;??}}我们看看编译完成后它是个什么样子:C:\>javacStringTest.javaC:\>javap-verboseStringTestCompiledfrom"StringTest.java"publicclassStringTestextendsjava.lang.Object?SourceFile:"StringTest.java"?minorversion:0?majorversion:50?Constantpool:const#1=Method???#9.#18;//?java/lang/Object."":()Vconst#2=String???#19;??//?abcconst#3=String???#20;??//?defconst#4=class????#21;??//?java/lang/StringBuilderconst#5=Method???#4.#18;//?java/lang/StringBuilder."":()Vconst#6=Method???#4.#22;//?java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;const#7=Method???#4.#23;//?java/lang/StringBuilder.toString:()Ljava/lang/String;const#8=class????#24;??//?StringTestconst#9=class????#25;??//?java/lang/Objectconst#10=Asciz???;const#11=Asciz???()V;const#12=Asciz???Code;const#13=Asciz???LineNumberTable;const#14=Asciz???main;const#15=Asciz???([Ljava/lang/String;)V;const#16=Asciz???SourceFile;const#17=Asciz???StringTest.java;const#18=NameAndType#10:#11;//?"":()Vconst#19=Asciz???abc;const#20=Asciz???def;const#21=Asciz???java/lang/StringBuilder;const#22=NameAndType#26:#27;//?append:(Ljava/lang/String;)Ljava/lang/StringBuilder;const#23=NameAndType#28:#29;//?toString:()Ljava/lang/String;const#24=Asciz???StringTest;const#25=Asciz???java/lang/Object;const#26=Asciz???append;const#27=Asciz???(Ljava/lang/String;)Ljava/lang/StringBuilder;;const#28=Asciz???toString;const#29=Asciz???()Ljava/lang/String;;?{publicStringTest();?Code:??Stack=1,Locals=1,Args_size=1??0:?aload_0??1:?invokespecial?#1;//Methodjava/lang/Object."":()V??4:?return?LineNumberTable:??line2:0?publicstaticvoidmain(java.lang.String[]);?Code:??Stack=2,Locals=4,Args_size=1??0:?ldc??#2;//Stringabc??2:?astore_1??3:?ldc??#3;//Stringdef??5:?astore_2??6:?new??#4;//classjava/lang/StringBuilder??9:?dup??10:?invokespecial?#5;//Methodjava/lang/StringBuilder."":()V??13:?aload_1??14:?invokevirtual?#6;//Methodjava/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;??17:?aload_2??18:?invokevirtual?#6;//Methodjava/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;??21:?invokevirtual?#7;//Methodjava/lang/StringBuilder.toString:()Ljava/lang/String;??24:?astore_3??25:?return?LineNumberTable:??line7:0??line8:3??line10:6??line13:25?}说明(这里不解释关于栈的计算指令,只说明大概意思):首先看到使用了一个指针指向一个常量池中的对象内容为“abc”,而另一个指针指向“def”,此时通过new申请了一个StringBuilder(jdk1.5以前是StringBuffer),然后调用这个StringBuilder的初始化方法;然后分别做了两次append操作,然后最后做一个toString()操作;可见String的+在编译后会被编译为StringBuilder来运行(关于为什么性能还是比StringBuilder慢那么多,文章后面来说明),我们知道这里做了一个newStringBuilder的操作,并且做了一个toString的操作,前面我们已经明确说明,凡是new出来的对象绝对不会放在常量池中;toString会发生一次内容拷贝,但是也不会在常量池中,所以在这里常量池String+常量池String放在了堆中;而下面这个后面那种情况呢,我们也用同样的方式来看看结果是什么,代码更简单了:publicclassStringTest{???publicstaticvoidmain(String[]args){????Stringd="abc"+"def";??}}看下结果:C:\>javacStringTest.javaC:\>javap-verboseStringTestCompiledfrom"StringTest.java"publicclassStringTestextendsjava.lang.Object?SourceFile:"StringTest.java"?minorversion:0?majorversion:50?Constantpool:const#1=Method???#4.#13;//?java/lang/Object."":()Vconst#2=String???#14;??//?abcdefconst#3=class????#15;??//?StringTestconst#4=class????#16;??//?java/lang/Objectconst#5=Asciz????;const#6=Asciz????()V;const#7=Asciz????Code;const#8=Asciz????LineNumberTable;const#9=Asciz????main;const#10=Asciz???([Ljava/lang/String;)V;const#11=Asciz???SourceFile;const#12=Asciz???StringTest.java;const#13=NameAndType#5:#6;//?"":()Vconst#14=Asciz???abcdef;const#15=Asciz???StringTest;const#16=Asciz???java/lang/Object;?{publicStringTest();?Code:??Stack=1,Locals=1,Args_size=1??0:?aload_0??1:?invokespecial?#1;//Methodjava/lang/Object."":()V??4:?return?LineNumberTable:??line2:0?publicstaticvoidmain(java.lang.String[]);?Code:??Stack=1,Locals=2,Args_size=1??0:?ldc??#2;//Stringabcdef??2:?astore_1??3:?return?LineNumberTable:??line11:0??line13:3}这下看下可能有人一下通透了,可能有人觉得更加模糊了,怎么编译完后比前面那个少那么多,是的,就是少那么多,因为当发生“abc”+“def”在同一行发生时,JVM在编译时就认为这个加号是没有用处的,编译的时候就直接变成成Stringd="abcdef";同理如果出现:Stringa=“a”+1,编译时候就会变成:Stringa=“a1″;再例如:finalStringa="a";finalStringb="ab";Stringc=a+b;在编译时候,c部分会被编译为:Stringc=“aab”;但是如果a或b有任意一个不是final的,都会new一个新的对象出来;其次再补充下,如果a和b,是某个方法返回回来的,不论方法中是final类型的还是常量什么的,都不会被在编译时将数据编译到常量池,因为编译器并不会跟踪到方法体里面去看你做了什么,其次只要是变量就是可变的,即使你认为你看到的代码是不可变的,但是运行时是可以被切入的。接收程序从Socket的InputStream读取数据时,字节就从RecvQ移动到Delivered中,而转移的块的大小依赖于RecvQ中的数据量和传递给read()方法的缓冲区的大小。