??xml version="1.0" encoding="utf-8" standalone="yes"?>精品国产电影,亚洲自啪免费,日韩成人综合 http://www.aygfsteel.com/liuyz2006/category/50541.htmlzh-cn Thu, 24 Mar 2016 17:45:26 GMT Thu, 24 Mar 2016 17:45:26 GMT 60 java 父子cL法多态调?/title> http://www.aygfsteel.com/liuyz2006/articles/429800.html阿?/dc:creator>阿?/author>Thu, 24 Mar 2016 10:17:00 GMT http://www.aygfsteel.com/liuyz2006/articles/429800.html http://www.aygfsteel.com/liuyz2006/comments/429800.html http://www.aygfsteel.com/liuyz2006/articles/429800.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/429800.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/429800.html 阅读全文 ]]> 谈Java中父cM子类的加载顺序详解(转) http://www.aygfsteel.com/liuyz2006/articles/429798.html阿?/dc:creator>阿?/author>Thu, 24 Mar 2016 09:37:00 GMT http://www.aygfsteel.com/liuyz2006/articles/429798.html http://www.aygfsteel.com/liuyz2006/comments/429798.html http://www.aygfsteel.com/liuyz2006/articles/429798.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/429798.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/429798.html 阅读全文 ]]> 解析 Java cd对象的初始化q程(转) http://www.aygfsteel.com/liuyz2006/articles/429797.html阿?/dc:creator>阿?/author>Thu, 24 Mar 2016 09:27:00 GMT http://www.aygfsteel.com/liuyz2006/articles/429797.html http://www.aygfsteel.com/liuyz2006/comments/429797.html http://www.aygfsteel.com/liuyz2006/articles/429797.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/429797.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/429797.html 阅读全文 ]]> javap的基本用?转) http://www.aygfsteel.com/liuyz2006/articles/429702.html阿?/dc:creator>阿?/author>Thu, 17 Mar 2016 09:22:00 GMT http://www.aygfsteel.com/liuyz2006/articles/429702.html javap 是JDK自带的反汇编器,可以查看java~译器ؓ我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作?/span>语法Q?/span> javap [ 命o选项 ] class. . . javap 命o用于解析cL件。其输出取决于所用的选项。若没有使用选项Q?/span>javap 输Z递给它的cȝ public 域及Ҏ?/span>javap 其输出到标准输备上?/span>命o选项 -help 输出 javap 的帮助信息?/span> -l 输出行及局部变量表?/span> -b 保?JDK 1.1 javap 的向后兼Ҏ?/span> -public 只显C?public cd成员?/span> -protected 只显C?protected ?public cd成员?/span> -package 只显C包、protected ?public cd成员。这是缺省设|?/span> -private 昄所有类和成员?/span> -J[flag] 直接?flag 传给q行时系l?/span> -s 输出内部cd{?/span> -c 输出cM各方法的未解析的代码Q即构成 Java 字节码的指o?/span> -verbose 输出堆栈大小、各Ҏ?locals ?args ?以及class文g的编译版?/span> -classpath[路径] 指定 javap 用来查找cȝ路径。如果设|了该选项Q则它将覆盖~省值或 CLASSPATH 环境变量。目录用冒号分隔?/span> -bootclasspath[路径] 指定加蝲自DcL用的路径。缺省情况下Q自丄是实现核?/span>Java q_的类Q位?jrelib 下面?br style="background-color: rgb(255, 255, 255);" /> -extdirs[dirs] 覆盖搜烦安装方式扩展的位|。扩展的~省位置?jrelibext?/span>
英文说明Q?/p>
C:\>javap -help Usage: javap <options> <classes>... where options include: -c Disassemble the code -classpath <pathlist> Specify where to find user class files -extdirs <dirs> Override location of installed extensions -help Print this usage message -J<flag> Pass <flag> directly to the runtime system -l Print line number and local variable tables -public Show only public classes and members -protected Show protected/public classes and members -package Show package/protected/public classes and members (default) -private Show all classes and members -s Print internal type signatures -bootclasspath <pathlist> Override location of class files loaded by the bootstrap class loader -verbose Print stack size, number of locals and args for methods If verifying, print reasons for failure
CZQ?/p>
下面也经典的StringBuilder代替String做字W串的例子?/p>
public class JAVAPTest { public static void main(String[] args) { } public static String contactWithStringNoLoopNoPara() { String s = "This is " + " my " + "first JAVAP test code." ; return s; } public static String contactWithStringNoLoop( int count) { String s = "This is " + " my " + count + "th JAVAP test code." ; return s; } public static String contactWithStringLoop( int count) { String s = "" ; for ( int i = 0 ; i < count; i++) { s += i; } return s; } public static String contactWithStringBufferLoop( int count) { StringBuffer sb = new StringBuffer(); for ( int i = 0 ; i < count; i++) { sb.append(i); } return sb.toString(); } } public class JAVAPTest {
public static void main(String[] args) {
}
public static String contactWithStringNoLoopNoPara() {
String s = "This is " + " my " + "first JAVAP test code.";
return s;
}
public static String contactWithStringNoLoop(int count) {
String s = "This is " + " my " + count + "th JAVAP test code.";
return s;
}
public static String contactWithStringLoop(int count) {
String s = "";
for (int i = 0; i < count; i++) {
s += i;
}
return s;
}
public static String contactWithStringBufferLoop(int count) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.append(i);
}
return sb.toString();
}
}
先编译:javac JAVAPTest.java
执行反编译:javap -c JAVAPTest //注意q个地方不需要class后缀?/p>
l果如下Q?/p>
Compiled from "JAVAPTest.java" public class JAVAPTest extends java.lang.Object{ public JAVAPTest(); Code: 0 : aload_0 1 : invokespecial # 1 ; 4 : return public static void main(java.lang.String[]); Code: 0 : return public static java.lang.String contactWithStringNoLoopNoPara(); Code: 0 : ldc # 2 ; 2 : astore_0 3 : aload_0 4 : areturn public static java.lang.String contactWithStringNoLoop( int ); Code: 0 : new # 3 ; 3 : dup 4 : invokespecial # 4 ; 7 : ldc # 5 ; 9 : invokevirtual # 6 ; 12 : iload_0 13 : invokevirtual # 7 ; 16 : ldc # 8 ; 18 : invokevirtual # 6 ; 21 : invokevirtual # 9 ; 24 : astore_1 25 : aload_1 26 : areturn public static java.lang.String contactWithStringLoop( int ); Code: 0 : ldc # 10 ; 2 : astore_1 3 : iconst_0 4 : istore_2 5 : iload_2 6 : iload_0 7 : if_icmpge 35 10 : new # 3 ; 13 : dup 14 : invokespecial # 4 ; 17 : aload_1 18 : invokevirtual # 6 ; 21 : iload_2 22 : invokevirtual # 7 ; 25 : invokevirtual # 9 ; 28 : astore_1 29 : iinc 2 , 1 32 : goto 5 35 : aload_1 36 : areturn public static java.lang.String contactWithStringBufferLoop( int ); Code: 0 : new # 11 ; 3 : dup 4 : invokespecial # 12 ; 7 : astore_1 8 : iconst_0 9 : istore_2 10 : iload_2 11 : iload_0 12 : if_icmpge 27 15 : aload_1 16 : iload_2 17 : invokevirtual # 13 ; 20 : pop 21 : iinc 2 , 1 24 : goto 10 27 : aload_1 28 : invokevirtual # 14 ; 31 : areturn } Compiled from "JAVAPTest.java"
public class JAVAPTest extends java.lang.Object{
public JAVAPTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
public static java.lang.String contactWithStringNoLoopNoPara();
Code:
0: ldc #2; //String This is my first JAVAP test code.
2: astore_0
3: aload_0
4: areturn
public static java.lang.String contactWithStringNoLoop(int);
Code:
0: new #3; //class java/lang/StringBuilder
3: dup
4: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
7: ldc #5; //String This is my
9: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: iload_0
13: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
16: ldc #8; //String th JAVAP test code.
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_1
25: aload_1
26: areturn
public static java.lang.String contactWithStringLoop(int);
Code:
0: ldc #10; //String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: iload_0
7: if_icmpge 35
10: new #3; //class java/lang/StringBuilder
13: dup
14: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
17: aload_1
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_2
22: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: astore_1
29: iinc 2, 1
32: goto 5
35: aload_1
36: areturn
public static java.lang.String contactWithStringBufferLoop(int);
Code:
0: new #11; //class java/lang/StringBuffer
3: dup
4: invokespecial #12; //Method java/lang/StringBuffer."<init>":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: iload_0
12: if_icmpge 27
15: aload_1
16: iload_2
17: invokevirtual #13; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
20: pop
21: iinc 2, 1
24: goto 10
27: aload_1
28: invokevirtual #14; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
31: areturn
} 有这个结果我们可以知道?p> 1。contactWithStringNoLoopNoParaҎ中,代码里面是字W串拼接Q貌似需要是用StringBuilder替换的好。其实在看了上面的反~译l果后,已经自动l合成一个固定字W串了。因此完全没有必要用StringBuilder?/p>
0: ldc #2; //String This is my first JAVAP test code.
2。contactWithStringNoLoopҎ中,因ؓ使用C变量Q貌似需要是用StringBuilder替换的好。其实在看了上面的反~译l果后,已经自动使用了StringBuilder。所以代码也没有必要使用StringBuilder?/p>
3. contactWithStringLoopҎ中,是@环拼接字W串Q貌似需要是用StringBuilder替换的好。看了反~译后,每个循环里面都各自生成了一个StringBuilderQƈStringBuilder.toString()防赋值给我们的Sring变量。而我们希望的是只生成一个StringBuilder对象。因此改为StringBuilder的好。@环的时候改为contactWithBufferLoop的方法最好?/p>
4.contactWithBufferLoopҎ中,是@环拼接字W串。也是我们预想的步骤在执行?br />
]]> [转]java基础Q父cM子类之间变量和方法的调用 http://www.aygfsteel.com/liuyz2006/articles/429596.html阿?/dc:creator>阿?/author>Thu, 10 Mar 2016 05:26:00 GMT http://www.aygfsteel.com/liuyz2006/articles/429596.html 1)父类构造函?br />java中当调用某个cȝ构造方法的时候,pȝM调用父类的非静态初始化块进行初始化Q这个调用是隐式的,而且父类的静态初始化代码 块L会被执行Q接着调用父类的一个或者多个构造器执行初始化,q个调用也可以通过superq行昑ּ调用?br />例如Q?br />父类代码如下Q?br />public class Creature {//父类 {//非静态代码块 System.out.println("creature的非静态代码块正在执行"); } public Creature(){ System.out.println("creature的构造函数正在执?); } } 子类代码如下Q?br />public class Animal extends Creature { { System.out.println("animal的初始化代码块正在执?); } public Animal(){ System.out.println("animal的构造方法正在执?); } public static void main(String[] args){ Animal a = new Animal() ; } } 则运行程序后的结果ؓQ?br />creature的非静态代码块正在执行 creature的构造函数正在执?br />animal的初始化代码块正在执?br />animal的构造方法正在执?br />从结果中可以看出Q调用某个类的构造方法的时候L会先执行父类的非静态代码块Q然后执行父cȝ构造方法,最后才是执行当前类?br />非静态代码块和构造方法。执行过E中有先后顺序?br />若果惌昑ּ调用父类的构造方法则可以使用super()Q来调用Q但是super关键字和this关键字都必须攑֜构造放的第一行,而且只能?br />用一个,Z么要攑֜W一行呢Q因为如果不攑֜W一行则先调用子cȝ初始化代码,再调用父cȝ初始化代码,则父cM的初始化后的?br />会覆盖子cM的初始化的倹{?br />注:super用于昑ּ调用父类的构造器Qthis可以昑ּ调用本类中的重蝲的构造器?br /> 2Q访问子cd象的实例变量 子类的方法可以访问父cM的实例变量,q是因ؓ子类l承父类׃获得父类中的成员变量和方法,但是父类Ҏ不能讉K子类的实例变?br />Q因为父cL本无法知道它被哪个cȝ承,它的子类会增加怎么L成员变量。但是,在极端的情况下,父类也可以访问子cM的变量?br />例如Q?br />父类代码如下Q?br />public class Base {//父类 private int i = 2 ; public Base(){ this.display() ; } public void display(){ System.out.println(i); } } 子类中代码如下: public class Derived extends Base { private int i = 22 ; public Derived(){ i = 222 ; } public void display(){ System.out.println(i); } } 试用例如下Q?br />public class Test { public static void main(String[] args) { new Derived() ; } } E序的执行结果ؓQ?br />0 也许你会感到奇怪,Z么不?Q?2Q?22Q怎么会是0呢,下面我们看一下程序的执行q程。当我们调用new Derived() ;创徏Derived 实例的时候,pȝ会ؓDerived对象分配内存I间QDerived会有两个i实例变量Q会分配两个I间来保存i的倹{分配完I间以后i的gؓ0 Q如果有引用cd则引用类型的gؓnull。接下来E序在执行Derived的构造器之前会执行Base的构造器Q表面上看Base的构造器中只?br />一行代码,但是在父cM定义i的时候执行的初始?Q因此经q编译之后,该构造方法中应该包含如下两行代码Q?br />i =2 ; this.display() ; E序先将Base中的i赋gؓ2Q然后执行displayҎ。此处有一个关键字thisQthis到底代表谁呢Q表面上看this代表的是Base的当前实例, 但是实际上代码是攑֜Derived的构造器中的Q所以this最l代表的是Derived的当前实例(~译cd是Base而实际引用一个Derived对象Q, 所以如果在父类的构造方法中直接输出System.out.println(this.i) ;则输出的l果?。但是调用this.display()ҎQ此时调用的?br />子类中重写的displayҎQ输出的变量i也是子类中的iQ但是此时子cM的变量iq没有赋|所以输出结果ؓ0?br />Z详细的看清楚this变量到底代表什么实例,我们Base的构造方法修改如下: public Base(){ System.out.println(this.i); System.out.println(this.getClass()); this.display() ; } 再次q行E序Q结果ؓQ?br />2 class edu.qichao.chapter2.Derived 0 可以看到this代表的是Derived的实例,但是~译的时候类型ؓBaseQ所以输出this.i的gؓ2?br /> 3Q调用被子类重写的方?br />默认情况下,子类可以调用父类的方法,但是父类不能调用子类的方法,因ؓ父类不知道它被哪个子类l承Q也不知道子cd增加怎么 LҎ?br />例如Q?br />父类Animal的代码如下: public class Animal { private String desc ; public Animal(){ this.desc = getDesc() ; } public String getDesc(){ return "Animal" ; } public String toString(){ return desc ; } } 子类Wolf的代码如下: public class Wolf extends Animal { private String name ; private double weight ; public Wolf(String name , double weight){ this.name = name ; this.weight = weight ; } public String getDesc(){ return "Wolf[name=" + name + ",weight=" + weight + "]" ; } public static void main(String[] args){ System.out.println(new Wolf("灰太? , 3)); } } E序的运行结果ؓQ?br />Wolf[name=null,weight=0.0] 现在我们分析一下程序执行的q程。在mainҎ中通过new Wolf("灰太? , 3)Q来创徏一个Wolf的实例,子类会隐式调用父cȝ构造方 法,在父cL造方法中初始化desc变量this.desc = getDesc() ;此处需要注意this变量Q虽然这个this攑֜Animal的构造放中,但是是在 Wolf的构造方法中调用父类的构造方法,所以this~译时类型ؓAnimalQ运行时cd为WolfQ此处调用的getDescҎ是子cWolf的方法, 但是子类中的name和weight变量都没有初始化Q默认ؓnull?.0.所以程序的最l结果ؓQWolf[name=null,weight=0.0] 4Q承成员变量和成员Ҏ的区?br />java中队成员变量的承和成员Ҏ的承是不同的?br />例如Q?br />父类代码如下Q?br />public class Base { int count = 2 ; public void display(){ System.out.println(this.count); } } 子类代码如下Q?br />public class Derived extends Base { int count = 20 ; @Override public void display(){ System.out.println(this.count); } } 试用例如下Q?br />public class Test { public static void main(String[] args) { Base b = new Base() ; System.out.println(b.count); b.display() ; System.out.println("-----------------"); Derived d = new Derived() ; System.out.println(d.count); d.display() ; System.out.println("-----------------"); Base bd = new Derived() ; System.out.println(bd.count); bd.display() ; System.out.println("-----------------"); Base d2b = d ; System.out.println(d2b.count); } } E序q行l果为: 2 2 ----------------- 20 20 ----------------- 2 20 ----------------- 2 在上面的E序中,不管是d变量、还是bd变量、还是都d2b变量。只要他们指向一个Derived对象Q则不管他们声明时用了什么类型,当通过 q些变量调用ҎӞҎ的行为L表现Z们的实际cd的行为,但是如果通过q些变量来访问他们所指向对象的实例变量的时候, q些实例变量的值L表现出声明这些变量所用类型的行ؓ。由此可见,java处理成员变量和成员方法的l承时是有区别的?img src ="http://www.aygfsteel.com/liuyz2006/aggbug/429596.html" width = "1" height = "1" /> ]]> java指o详解Q{Q?/title> http://www.aygfsteel.com/liuyz2006/articles/418243.html阿?/dc:creator>阿?/author>Wed, 24 Sep 2014 10:10:00 GMT http://www.aygfsteel.com/liuyz2006/articles/418243.html http://www.aygfsteel.com/liuyz2006/comments/418243.html http://www.aygfsteel.com/liuyz2006/articles/418243.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/418243.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/418243.html 阅读全文 ]]> 《深入理解Java虚拟机》笔?/title> http://www.aygfsteel.com/liuyz2006/articles/416473.html阿?/dc:creator>阿?/author>Sat, 02 Aug 2014 10:06:00 GMT http://www.aygfsteel.com/liuyz2006/articles/416473.html 阅读全文 ]]> java堆栈Ҏ区简单分析(转) http://www.aygfsteel.com/liuyz2006/articles/410339.html阿?/dc:creator>阿?/author>Wed, 26 Feb 2014 09:50:00 GMT http://www.aygfsteel.com/liuyz2006/articles/410339.html http://www.360doc.com/content/11/0504/12/3903749_114271703.shtml ]]> 深入理解JVM—字节码执行引擎(转) http://www.aygfsteel.com/liuyz2006/articles/410168.html阿?/dc:creator>阿?/author>Fri, 21 Feb 2014 10:06:00 GMT http://www.aygfsteel.com/liuyz2006/articles/410168.html http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ ]]> Java语言基础 http://www.aygfsteel.com/liuyz2006/articles/409487.html阿?/dc:creator>阿?/author>Sun, 02 Feb 2014 09:13:00 GMT http://www.aygfsteel.com/liuyz2006/articles/409487.html http://blog.csdn.net/linzhengqun/article/category/800320 java语音基础知识Q?br />类(1) 多线E?br />RTTI 异常机制 抽象cd接口 对象的初始化 基本数组cd 内部c?br />泛型 final和static ]]> Java语言基础Q对象的初始?(转) http://www.aygfsteel.com/liuyz2006/articles/409484.html阿?/dc:creator>阿?/author>Sun, 02 Feb 2014 07:55:00 GMT http://www.aygfsteel.com/liuyz2006/articles/409484.html
]]> java中覆盖和隐藏的问?转) http://www.aygfsteel.com/liuyz2006/articles/409423.html阿?/dc:creator>阿?/author>Wed, 29 Jan 2014 01:46:00 GMT http://www.aygfsteel.com/liuyz2006/articles/409423.html
java中覆盖和隐藏的问?/h2>
q期复习javaӞ发觉了自己很多没掌握的知识点Q现在每天ȝ一点点Q一点点的积累,一点点的进步?/p>
今天的解决问?#8212;—java中覆盖和隐藏的问题(Ҏ和变量)
参考网址Q?a >http://school.cnd8.com/java/jiaocheng/10836.htm
http://heisetoufa.javaeye.com/blog/227345
1.先来ȝjava中方法的覆盖和隐?/p>
一个大的原则:静态方法不能被覆盖。实例方法被覆盖Q静态方法被隐藏。被覆盖的方法只有覆盖它们的cL能访问它们,而访问被隐藏的方法是提供该方法的全局名?/p>
例子Q?/p>
01: class Super 02: { 03: static String greeting() 04: { 05: return "Goodnight"; 06: } 07: 08: String name() 09: { 10: return "Richard"; 11: } 12: } 01: class Sub extends Super 02: { 03: static String greeting() 04: { 05: return "Hello"; 06: } 07: 08: String name() 09: { 10: return "Dick"; 11: } 12: } 01: class Test 02: { 03: public static void main(String[] args) 04: { 05: Super s = new Sub(); 06: System.out.println(s.greeting() + ", " + s.name()); 07: } 08: } E序q行l果QGoodnightQDick 分析Q在main函数中,创徏了一个子csub对象实例Q通过赋值号我们可以看成其被强制转换成父csupercd。由于greeting是静态方法,它仅仅是被子csub隐藏Q所以通过强制转换成父csuper的对象实例s调用Ӟ实际上调用的是父cȝgreetingҎQ而nameҎ为实例方法,其被子类sub覆盖Q所以s.name()是调用的子类nameҎ?/pre>在承时需要注意的几点原则Q?/pre>1Q试囄子类的静态方法隐藏父cM同样标识的实例方法不合法Q编译器会报错; 2Q试囄子类的实例方法覆盖父cM同样标识的静态方法也不合法,~译器会报错Q?/pre>3Q静态方法和最l方法不能被覆盖Q?/pre>4Q实例方法能够被覆盖Q?/pre>5Q抽象方法必d具体cM被覆盖?/pre>2.再来ȝ下变量的覆盖和隐?/pre>原网址的变量分的很详细Q不仔细看还被绕的有点糊涂。ȝ了下Q不是静态变量还是非静态变量,只要是成员变量,它们被覆盖和被隐藏的原则一栗原则:成员变量能够被子cd名的成员变量隐藏Q而局部变量和形参不会被隐藏?/pre>例子Q?/pre>class Base { int x = 1; static int y=2; int z=3; int method() { return x; } } class Subclass extends Base { int x = 4; int y=5; static int z=6; int method() { return x; } } public class Test { public static void main(String[] args) { Subclass s=new Subclass(); System.out.println(s.x + " " + s.y +" "+ s.z); System.out.println(s.method()); Base b = (Subclass)s; System.out.println(b.x + " " + b.y +" "+ b.z); System.out.println(b.method()); } } l果Q? 5 6 4 1 2 3 4 分析Q在mainҎ中,开始创Z一个subclass对象实例Q对于第一个输出很好理解;后将对象实例s强制转换成父cBasecdQ由于父cȝ成员变量只是被隐藏,所以通过强制转换成父cȝ型的对象实例调用Ӟ调用的是父类中的变量Q而methodҎ是被子类同名Ҏ所覆盖Q所以调用时依然调用的子cmethodҎ?br /> 3.最后变量和Ҏ的隐藏及其覆盖的不同 一个类的实例无法通过使用全局名或者强制自p{换成父类型,来访问父cM被隐藏的ҎQ但是可以通过强制转换为父cd之后Q访问父cd中被隐藏的变量。静态方法不能覆盖父cȝ实例ҎQ而静态变量却可以隐藏父类的一个同名实例变量。实例方法不能覆盖父cȝ同名静态方法,而变量却可以隐藏父类的同名成员变量?br /> 4.我最l发现和解决的问?br />public class ClassA{ public void methodOne(int i){} public void methodTwo(int i){} public static void methodThree(int i){} public static void methodFour(int i){} } public class ClassB{ public static void methodOne(int i){} public void methodTwo(int i){} public void methodThree(int i){} public static void methodFour(int i){} } a.哪些Ҏ覆盖了超cM的方法? methodTwo b.哪些Ҏ隐藏了超cM的方法? methodFour 其他两个Ҏ~译会报错,因ؓ不能用子cȝ静态方法隐藏父cM同名的实例方法,不能用子cȝ实例Ҏ覆盖父类中同名的静态方法?br /> ]]>Runnable和Thread的区?转) http://www.aygfsteel.com/liuyz2006/articles/408157.html阿?/dc:creator>阿?/author>Sat, 28 Dec 2013 08:54:00 GMT http://www.aygfsteel.com/liuyz2006/articles/408157.html 在java中可有两U方式实现多U程Q一U是l承Threadc,一U是实现Runnable接口QThreadcL在java.lang包中定义的。一个类只要l承了Threadcd时覆写了本类中的run()Ҏ可以实现多U程操作了,但是一个类只能l承一个父c,q是此方法的局限,
下面看例子:
package org.thread.demo;
class MyThread extends Thread{
private String name;
public MyThread(String name) {
super();
this.name = name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println("U程开始:"+this.name+",i="+i);
}
}
}
package org.thread.demo;
public class ThreadDemo01 {
public static void main(String[] args) {
MyThread mt1=new MyThread("U程a");
MyThread mt2=new MyThread("U程b");
mt1.run();
mt2.run();
}
}
但是Q此时结果很有规律,先第一个对象执行,然后W二个对象执行,q没有相互运行。在JDK的文档中可以发现Q一旦调用start()ҎQ则会通过JVM扑ֈrun()Ҏ。下面启?/p>
start()Ҏ启动U程Q?/p>
package org.thread.demo;
public class ThreadDemo01 {
public static void main(String[] args) {
MyThread mt1=new MyThread("U程a");
MyThread mt2=new MyThread("U程b");
mt1.start();
mt2.start();
}
};q样E序可以正常完成交互式运行。那么ؓ啥非要用start();Ҏ启动多线E呢Q?/p>
在JDK的安装\径下Qsrc.zip是全部的java源程序,通过此代码找到Thread中的start()Ҏ的定义,可以发现此方法中使用了private native void start0();其中native关键字表C可以调用操作系l的底层函数Q那么这L技术成为JNI技术(java Native InterfaceQ?/p>
·Runnable接口
在实际开发中一个多U程的操作很用Threadc,而是通过Runnable接口完成?/p>
public interface Runnable{
public void run();
}
例子Q?/p>
package org.runnable.demo;
class MyThread implements Runnable{
private String name;
public MyThread(String name) {
this.name = name;
}
public void run(){
for(int i=0;i<100;i++){
System.out.println("U程开始:"+this.name+",i="+i);
}
}
};
但是在用Runnable定义的子cM没有start()ҎQ只有ThreadcM才有。此时观察Threadc,有一个构造方法:public Thread(Runnable targer)此构造方法接受Runnable的子cd例,也就是说可以通过ThreadcL启动Runnable实现的多U程。(start()可以协调pȝ的资源):
package org.runnable.demo;
import org.runnable.demo.MyThread;
public class ThreadDemo01 {
public static void main(String[] args) {
MyThread mt1=new MyThread("U程a");
MyThread mt2=new MyThread("U程b");
new Thread(mt1).start();
new Thread(mt2).start();
}
}
· 两种实现方式的区别和联系Q?/p>
在程序开发中只要是多U程肯定永远以实现Runnable接口ZQ因为实现Runnable接口相比
l承ThreadcL如下好处Q?/p>
->避免点承的局限,一个类可以l承多个接口?/p>
->适合于资源的׃n
以卖程序ؓ例,通过Threadcd成:
package org.demo.dff;
class MyThread extends Thread{
private int ticket=10;
public void run(){
for(int i=0;i<20;i++){
if(this.ticket>0){
System.out.println("卖票Qticket"+this.ticket--);
}
}
}
};
下面通过三个U程对象Q同时卖:
package org.demo.dff;
public class ThreadTicket {
public static void main(String[] args) {
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
MyThread mt3=new MyThread();
mt1.start();//每个U程都各卖了10张,共卖?0张票
mt2.start();//但实际只?0张票Q每个线E都卖自q?/p>
mt3.start();//没有辑ֈ资源׃n
}
}
如果用Runnable可以实现资源共享,下面看例子:
package org.demo.runnable;
class MyThread implements Runnable{
private int ticket=10;
public void run(){
for(int i=0;i<20;i++){
if(this.ticket>0){
System.out.println("卖票Qticket"+this.ticket--);
}
}
}
}
package org.demo.runnable;
public class RunnableTicket {
public static void main(String[] args) {
MyThread mt=new MyThread();
new Thread(mt).start();//同一个mtQ但是在Thread中就不可以,如果用同一
new Thread(mt).start();//个实例化对象mtQ就会出现异?/p>
new Thread(mt).start();
}
};
虽然现在E序中有三个U程Q但是一共卖?0张票Q也是说用Runnable实现多线E可以达到资源共享目的?/p>
Runnable接口和Thread之间的联p:
public class Thread extends Object implements Runnable
发现ThreadcM是Runnable接口的子cR?/p>
]]> java对象的生命周期及回收Q{Q?/title> http://www.aygfsteel.com/liuyz2006/articles/407924.html阿?/dc:creator>阿?/author>Mon, 23 Dec 2013 08:52:00 GMT http://www.aygfsteel.com/liuyz2006/articles/407924.html
要理解java对象的生命周期,我们需要要明白两个问题Q?/p>
1、java是怎么分配内存?,2、java是怎么回收内存的?/p>
喜欢java的hQ往往因ؓ它的内存自动理机制Q不喜欢java的hQ往往也是因ؓ它的内存自动理。我属于前者,q几q的codingl验让我认识刎ͼ要写好javaE序Q理解java的内存管理机制是多么的重要。Q何语aQ内存管理无外乎分配和回Ӟ在C中我们可以用malloc动态申请内存,调用free释放甌的内存;在C++中,我们可以用new操作W在堆中动态申请内存,~写析构函数调用delete释放甌的内存;那么在java中究竟是内存怎样理的呢Q要弄清q个问题Q我们首先要了解java内存的分配机Ӟ在java虚拟范里QJVM被分?个内存区域,但是规范q毕竟只是规范,像我们~写的接口一P虽然最l行Z_但是个h的实现可能千差万别,各个厂商的JVM实现也不相同,在这里,我们只针对sun的Hotspot虚拟?该虚拟机也是目前应用最q泛的虚拟机?/p>
虚拟器规范中?个内存区域分别是三个U程U有的和四个U程׃n的内存区,U程U有的内存区域与U程h相同的生命周期,它们分别是: 指o计数器?U程栈和本地U程栈,四个׃n区是所有线E共享的Q在JVM启动时就会分?分别是:Ҏ区?帔R池、直接内存区和堆Q即我们通常所说的JVM的内存分为堆和栈中的堆,后者就是前面的U程栈)。接下来我们逐一了解q几个内存区域?/p>
1 指o计数器。我们都知道java的多U程是通过JVM切换旉片运行的Q因此每个线E在某个时刻可能在运行也可能被挂P那么当线E挂起之后,JVM再次调度它时怎么知道该线E要q行那条字节码指令呢Q这需要一个与该线E相关的内存区域记录该线E下一条指令,而指令计数器是实现q种功能的内存区域。有多少U程在编译时是不定的,因此该区域也没有办法在编译时分配Q只能在创徏U程时分配,所以说该区域是U程U有的,该区域只是指令的计数Q占用的I间非常,所以虚拟机规范中没有ؓ该区域规定OutofMemoryError?/p>
2 U程栈。先让我看以下一D代?
class Test{ public static void main(String[] args) { Thread th = new Thread(); th.start(); } } class Test{
public static void main(String[] args) {
Thread th = new Thread();
th.start();
}
}
在运行以上代码时QJVM分配一块栈I间l线EthQ用于保存方法内的局部变量,Ҏ的入口和出口{,q些局部变量包括基本类型和对象引用cdQ这里可能有Z问,java的对象引用不是分配在堆上吗?有这L惑的人,可能是没有理解java中引用和对象之间的区别,当我们写Z下代码时:
public Object test(){ Object obj = new Object(); return obj; } public Object test(){
Object obj = new Object();
return obj;
}
其中的Object obj是我们所说的引用cdQ这L声明本n是要占用4个字节,而这4个字节在q里是在栈I间里分配的Q准的说是在线E栈中ؓtestҎ分配的栈帧中分配的,当方法退出时Q将会随栈的弹自动销毁,而new Object()则是在堆中分配的Q由GC在适当的时间收回其占用的空间。每个栈I间的默认大ؓ0.5MQ在1.7里调整ؓ1MQ每调用一ơ方法就会压入一个栈帧,如果压入的栈帧深度过大,x法调用层ơ过?׃抛出StackOverFlow,QSOF最常见的场景就是递归中,当递归没办法退出时Q就会抛此异常,Hotspot提供了参数设|改区域的大,使用-XssQxxKQ就可以修改默认大小?3 本地U程?思义Q该区域主要是给调用本地Ҏ的线E分配的Q该区域和线E栈的最大区别就是,在该U程的申L内存不受GC理Q需要调用者自q理,JDK中的Mathcȝ大部分方法都是本地方法,一个值得注意的问题是,在执行本地方法时Qƈ不是q行字节码,所以之前所说的指o计数器是没法记录下一条字节码指o的,当执行本地方法时Q指令计数器|ؓundefined?接下来是四个U程׃n区?1 Ҏ区。这块区域是用来存放JVM装蝲的class的类信息Q包括:cȝҎ、静态变量、类型信?接口/父类)Q我们用反技术时Q所需的信息就是从q里获取的?2 帔R池。当我们~写如下的代码时Q?/p>
class Test1{ private final int size= 50 ; } class Test1{
private final int size=50;
}
q个E序中size因ؓ用final修饰Q不能再修改它的|所以就成ؓ帔RQ而这帔R会存放在常量区Q这些常量在~译时就知道占用I间的大,但ƈ不是说明该区域编译就固定了,q行期也可以修改帔R池的大小Q典型的场景是在使用StringӞ你可以调用String?intern()QJVM会判断当前所创徏的String对象是否在常量池中,若有Q则从常量区取,否则把该字符攑օ帔R池ƈq回,q时׃修改帔R池的大小Q比如JDK中java.io.ObjectStreamField的一D代?
ObjectStreamField(Field field, boolean unshared, boolean showType) { this .field = field; this .unshared = unshared; name = field.getName(); Class ftype = field.getType(); type = (showType || ftype.isPrimitive()) ? ftype : Object. class ; signature = ObjectStreamClass.getClassSignature(ftype).intern(); } ObjectStreamField(Field field, boolean unshared, boolean showType) {
this.field = field;
this.unshared = unshared;
name = field.getName();
Class ftype = field.getType();
type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
signature = ObjectStreamClass.getClassSignature(ftype).intern();
}
q段代码获取的cȝ{攑օ帔R池。HotSpot中ƈ没有单独区域分配Q而是合ƈ到方法区中?3 直接内存区。直接内存区q不是JVM可管理的内存区。在JDK1.4中提供的NIO中,实现了高效的R/W操作Q这U高效的R/W操作是通过道机制实现的,而管道机制实际上使用了本地内存,q样避免了从本地源文g复制JVM内存Q再从JVM复制到目标文件的q程Q直接从源文件复制到目标文gQJVM通过DirectByteBuffer操作直接内存?4 堆。主角L最后出场,堆绝ҎJVM中的一{公民,l对的主角,我们通常所说的GC主要是在这块区域中q行的,所有的java对象都在q里分配Q这也是JVM中最大的内存区域Q被所有线E共享,成千上万的对象在q里创徏Q也在这里被销毁?java内存分配到这q是一个完l了Q接下来我们讨论java内存的回收机Ӟ 内存回收主要包含以下几个斚w理解Q?W一Q局部变量占用内存的回收Q所谓局部变量,是指在Ҏ内创建的变量Q其中变量又分ؓ基本cd和引用类型。如下代?
public void test(){ int x= 1 ; char y= 'a' ; long z=10L; } public void test(){
int x=1;
char y='a';
long z=10L;
}
变量x y z即ؓ局部变量,占用的空间将在test()所在的U程栈中分配Qtest()执行完了后会自动从栈中弹出,释放其占用的内存Q再来看一D代码:
public void test2(){ Date d = new Date(); System.out.println( "Now is " +d); } public void test2(){
Date d = new Date();
System.out.println("Now is "+d);
}
我们都知道上qC码会创徏两个对象Q一个是Date d另一个是new Date。Date d叫做声明了一个datecd的引用,引用是一U类型,和int x一P它表明了q种cd要占用多空_在java中引用类型和intcd一样占?字节的空_如果只声明引用而不赋|q?个字节将指向JVM中地址?的空_表示未初始化Q对它的M操作都会引发I指针异常?如果q行赋值如d = new Date()那么q个d׃存了new DateQ)q个对象的地址Q通过之前的内存分配策略,我知道new DateQ)是在jvm的heap中分配的Q其占用的空间的回收我们在后面着重分析,q里我们要知道的是这个Date d所占用的空间是在test2()所在的U程栈分配的Q方法执行完后同样会被弹出栈Q释攑օ占用的空间?W二.非局部变量的内存回收,在上面的代码中new Date()和C++里的new创徏的对象一P是在heap中分配,其占用的I间不会随着Ҏ的结束而自动释N要一定的机制d除,在C++中必ȝE序员在适当时候delete掉,在java中这部分内存是由GC自动回收的,但是要进行内存回收必解决两问题Q那些对象需要回收、怎么回收。判定那些对象需要回Ӟ我们熟知的有以下ҎQ?一Q引用计数法Q这应是l大数的的java E序员听说的Ҏ了,也是很多书上甚至很多老师讲的ҎQ该Ҏ是这hq的Qؓ每个对象l护一个引用计数器Q当有引用时加1Q引用解除时减1Q那些长旉引用?的对象就判定为回收对象,理论上这L判定是最准确的,判定的效率也高,但是却有一个致命的~陷Q请看以下代码:
package tmp; import java.util.ArrayList; import java.util.List; public class Test { private byte [] buffer; private List ls; public Test() { this .buffer = new byte [ 4 * 1024 * 1024 ]; this .ls = new ArrayList(); } private List getList() { return ls; } public static void main(String[] args) { Test t1 = new Test(); Test t2 = new Test(); t1.getList().add(t2); t2.getList().add(t1); t1 = t2 = null ; Test t3 = new Test(); System.out.println(t3); } } package tmp;
import java.util.ArrayList;
import java.util.List;
public class Test {
private byte[] buffer;
private List ls;
public Test() {
this.buffer = new byte[4 * 1024 * 1024];
this.ls = new ArrayList();
}
private List getList() {
return ls;
}
public static void main(String[] args) {
Test t1 = new Test();
Test t2 = new Test();
t1.getList().add(t2);
t2.getList().add(t1);
t1 = t2 = null;
Test t3 = new Test();
System.out.println(t3);
}
}
我们用以下参数运行:-Xmx10M -Xms10M M jvm的大设|ؓ10MQ不允许扩展Q按引用计数法,t1和t2怺引用Q他们的引用计数都不可能?Q那么他们将永远不会回收Q在我们的环境中JVM?0MQt1 t2占用8mQ那么剩下的2MQ是不以创建t3的,理论上应该抛出OOM。但是,E序正常q行了,q说明JVM应该是回收了t1和t2的我们加?XX:+PrintGCDetailsq行Q将打印GC的回收日?
[GC [DefNew: 252K->64K(960K), 0.0030166 secs][Tenured: 8265K->137K(9216K), 0.0109869 secs] 8444K->137K(10176K), [Perm : 2051K->2051K(12288K)], 0.0140892 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
[GC [DefNew: 252K->64K(960K), 0.0030166 secs][Tenured: 8265K->137K(9216K), 0.0109869 secs] 8444K->137K(10176K), [Perm : 2051K->2051K(12288K)], 0.0140892 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
com.mail.czp.Test@2ce908
Heap
def new generation total 960K, used 27K [0x029e0000, 0x02ae0000, 0x02ae0000)
eden space 896K, 3% used [0x029e0000, 0x029e6c40, 0x02ac0000)
from space 64K, 0% used [0x02ad0000, 0x02ad0000, 0x02ae0000)
to space 64K, 0% used [0x02ac0000, 0x02ac0000, 0x02ad0000)
tenured generation total 9216K, used 4233K [0x02ae0000, 0x033e0000, 0x033e0000)
the space 9216K, 45% used [0x02ae0000, 0x02f02500, 0x02f02600, 0x033e0000)
compacting perm gen total 12288K, used 2077K [0x033e0000, 0x03fe0000, 0x073e0000)
the space 12288K, 16% used [0x033e0000, 0x035e74d8, 0x035e7600, 0x03fe0000)
No shared spaces configured.
从打印的日志我们可以看出QGC照常回收了t1 t2,q就从侧面证明jvm不是采用q种{略判定对象是否可以回收的?/p>
二,Ҏ索算法,q是当前的大部分虚拟机采用的判定{略QGCU程q行Ӟ它会以一些特定的引用作ؓLUCؓGCRootQ从q些L开始搜索,把所用与q些L相关联的对象标记QŞ成几条链路,扫描完时Q那些没有与M链\惌接的对象׃判定为可回收对象。具体那些引用作v点呢Q一U是cȝ别的引用Q静态变量引用、常量引用,另一U是Ҏ内的引用Q如之前的test()Ҏ中的Date d对new Date()的引用,在我们的试代码中,在创建t3Ӟjvm发现当前的空间不以创徏对象Q会出发一ơGCQ虽然t1和t2怺引用Q但是执行t1=t2=null后,他们不和上面?个根引用中的M一个相q接Q所以GC会判定他们是可回收对象,q在随后其回收Q从而ؓt3的创建创造空_当进行回收后发现I间q是不够Ӟ׃抛出OOM?/p>
接下来我们就该讨论GC 是怎么回收的了Q目前版本的Hotspot虚拟机采用分代回收算法,它把heap分ؓ新生代和老年代两块区?如下?
默认的配|中老年代占90% 新生代占10%Q其中新生代又被分ؓ一个eden区和两个survivor区,每次使用eden和其中的一个survivor区,一般对象都在eden和其中的一个survivor区分配,但是那些占用I间较大的对象,׃直接在老年代分配,比如我们在进行文件操作时讄的缓冲区Q如byte[] buffer = new byte[1024*1024],q样的对象如果在新生代分配将会导致新生代的内存不频J的gcQGCq行旉先会q行会在新生代进行,会把那些标记q在引用的对象复制到另一块survivorI间中,然后把整个eden区和另一个survivor区里所有的对象q行清除Q但也ƈ不是立即清除Q如果这些对象重写了finalizeҎQ那么GC会把q些对象先复制到一个队列里Q以一个低U别的线E去触发finalizeҎQ然后回收该对象Q而那些没有覆写finalizeҎ的对象,会直接被回收。在复制存活对象到另一个survivorI间的过E中可能会出现空间不的情况Q在q种情况下GC回直接把q些存活对象复制到老年代中Q如果老年代的I间也不够时Q将会触发一ơFull GC,Full gc会回收老年代中那些没有和Q何GC Root相连的对象,如果Full GC后发现内存还是不I会出现OutofMemoryError?/p>
Hotspot虚拟Zjava对象内存的分配和回收到此q完结?/p>
大小: 11.1 KB ]]> 析JVM内存l构?大区?转) http://www.aygfsteel.com/liuyz2006/articles/401543.html阿?/dc:creator>阿?/author>Sun, 14 Jul 2013 02:13:00 GMT http://www.aygfsteel.com/liuyz2006/articles/401543.html 析JVM内存l构?大区?/h1>
内存作ؓpȝ中重要的资源Q对于系l稳定运行和高效q行起到了关键的作用QJava和C之类的语a不同Q不需要开发h员来分配内存和回收内存,而是由JVM来管理对象内存的分配以及对象内存的回Ӟ又称为垃圑֛收、GCQ,q对于开发h员来说确实大大降低了~写E序的难度,但带来的一个副作用是Q当pȝq行q程中出现JVM抛出的内存异常(例如OutOfMemoryErrorQ的时候,很难知道原因是什么,另外一斚wQ要~写高性能的程序,通常需要借助内存来提升性能Q因此如何才能合理的使用内存以及让JVM合理的进行内存的回收是必L握的Q本文将?/div>
其实对于我们一般理解的计算机内存,它算是CPU与计机打交道最频繁的区域,所有数据都是先l过盘臛_存,然后由CPU再从内存中获取数据进行处理,又将数据保存到内存,通过分页或分片技术将内存中的数据再flush至硬盘。那JVM的内存结构到底是如何呢?JVM做ؓ一个运行在操作pȝ上,但又独立于osq行的^収ͼ它的内存臛_应该包括象寄存器、堆栈等区域?/p>
JVM在运行时数据划分ؓ?个区域来存储Q而不仅仅是大家熟知的Heap区域Q这6个区域图C如下:
JVM内存的分配结构示意图
下面逐一介绍下各个区域所做的工作及其充当的功能?/p>
PC Register(PC寄存?
PC寄存器是一块很的内存区域Q主要作用是记录当前U程所执行的字节码的行受字节码解释器工作时是通过改变当前U程的程序计数器选取下一条字节码指o来工作的。Q何分支,循环Q方法调用,判断Q异常处理,U程{待以及恢复U程Q递归{等都是通过q个计数器来完成的?/p>
׃Java多线E是通过交替U程轮流切换q分配处理器旉的方式来实现的,在Q何一个确定的旉里,在处理器的一个内核只会执行一条线E中的指令。因此ؓ了线E等待结束需要恢复到正确的位|执行,每条U程都会有一个独立的E序计数器来记录当前指o的行受计数器之间怺独立互不影响Q我们称q块内存?#8220;U程U有”的内存?/p>
如果所调用的方法ؓnative的,则PC寄存器中不存储Q何信息?/p>
l JVM?/p>
JVM栈是U程U有的,每个U程创徏的同旉会创建JVM栈,JVM栈中存放的ؓ当前U程中局部基本类型的变量Qjava中定义的八种基本cdQboolean、char、byte、short、int、long、float、doubleQ、部分的q回l果以及Stack FrameQ非基本cd的对象在JVM栈上仅存放一个指向堆上的地址Q因此Java中基本类型的变量是g递,而非基本cd的变量是引用传递,Sun JDK的实CJVM栈的I间是在物理内存上分配的Q而不是从堆上分配?/p>
׃JVM栈是U程U有的,因此其在内存分配上非帔R效,q且当线E运行完毕后Q这些内存也p自动回收?/p>
当JVM栈的I间不Ӟ会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定栈的大,例如如下代码Q?/p>
new Thread( new Runnable(){ public void run() { loop(0); } private void loop ( int i){ if (i!=1000){ i++; loop (i); } else { return ; } } }).start();
当JVM参数讄?Xss1KQ运行后会报出类g面的错误Q?/p>
Exception in thread "Thread-0"java.lang.StackOverflowError
l 堆(HeapQ?/p>
Heap是大家最为熟悉的区域Q它是JVM用来存储对象实例以及数组值的区域Q可以认为Java中所有通过new创徏的对象的内存都在此分配,Heap中的对象的内存需要等待GCq行回收QHeap?2位的操作pȝ上最大ؓ2GQ在64位的操作pȝ上则没有限制Q其大小通过-Xms?Xmx来控Ӟ-Xms为JVM启动时申L最Heap内存Q默认ؓ物理内存?/64但小?GQ?Xmx为JVM可申L最大Heap内存Q默认ؓ物理内存?/4Q默认当IZ堆内存小?0%ӞJVM会增大Heap的大到-Xmx指定的大,可通过-XX:MinHeapFreeRatio=来指定这个比例,当空余堆内存大于70%ӞJVM会将Heap的大往-Xms指定的大调_可通过-XX:MaxHeapFreeRatio=来指定这个比例,但对于运行系l而言Qؓ了避免频J的Heap Size的大,通常都会?Xms?Xmx的D成一P因此q两个用于调整比例的参数通常是没用的。其实jvm中对于堆内存的分配、用、管理、收集等有更为精巧的设计Q具体可以在JVM堆内存分析中q行详细介绍?/p>
当堆中需要用的内存过其允许的大小Ӟ会抛出OutOfMemory的错误信息?/p>
l Ҏ区域QMethodAreaQ?/p>
Ҏ区域存放了所加蝲的类的信息(名称、修饰符{)、类中的静态变量、类中定义ؓfinalcd的常量、类中的Field信息、类中的Ҏ信息Q当开发h员在E序中通过Class对象中的getName、isInterface{方法来获取信息Ӟq些数据都来源于Ҏ区域Q可见方法区域的重要性。同PҎ区域也是全局׃n的,它在虚拟机启动时在一定的条g下它也会被GCQ当Ҏ区域需要用的内存过其允许的大小Ӟ会抛出OutOfMemory的错误信息?/p>
在Sun JDK中这块区域对应的为PermanetGenerationQ又UCؓ持久代,默认?4MQ可通过-XX:PermSize以及-XX:MaxPermSize来指定其大小?/p>
l q行时常量池QRuntimeConstant PoolQ?/p>
cMC中的W号表,存放的ؓcM的固定的帔R信息、方法和Field的引用信息等Q其I间从方法区域中分配。类或接口的帔R池在该类的class文g被java虚拟机成功装载时分配?/p>
l 本地Ҏ堆栈QNativeMethod StacksQ?/p>
JVM采用本地Ҏ堆栈来支持nativeҎ的执行,此区域用于存储每个nativeҎ调用的状态?/p>
例如有这么一D代码:
public class A { public static void main(String[]args){ String a="a" ; String b="b" ; String ab="ab" ; System.out.println((a+b)==ab); System.out.println(("a" + "b" )==ab); final String afinal= "a" ; String result=afinal+"b" ; System.out.println(result==ab); String plus=a+"b" ; System.out.println(plus==ab); System.out.println(plus.intern()==ab); } }
分析下上面代码执行的l果Q可通过javap –verbose A来辅助理解分析?/p>
l (a+b)==ab
a+b是两个变量相加,需要到q行时才能确定其|到运行时后JVM会ؓ两者相加后产生一个新的对象,因此a+b==ab的结果ؓfalse?/p>
l (“a”+”b”)==ab
“a”+”b”是常量,在编译时JVM已经其变ؓ”ab”字符串了Q而ab=”ab”也是帔RQ这两者在帔R池即为同一地址Q因?“a”+”b”)==ab为true?/p>
l result==ab
result=afinal+”b”Qafinal是个final的变量, result在编译时也已l被转变Z”ab”Q和”ab”在常量池中同样ؓ同一地址Q因此result==ab为true?/p>
l plus=ab
plus和a+b的情冉|相同的,因此plus==ab为false?/p>
l plus.intern()==ab
q里的不同点在于调用了plus.intern()ҎQ这个方法的作用是获取plus指向的常量池地址Q因此plus.intern()==ab为true?/p>
在掌握了JVM对象内存分配的机制后Q接下来看看JVM是如何做到自动的对象内存回收的,q里指的的是Heap以及Method Area的回Ӟ其他几个区域的回攉由JVM单的按生命周期来q行理
原文链接Qhttp://blog.csdn.net/zhaozheng7758/article/details/8623562
]]>
详解JVM工作原理和特点(转) http://www.aygfsteel.com/liuyz2006/articles/401541.html阿?/dc:creator>阿?/author>Sat, 13 Jul 2013 15:11:00 GMT http://www.aygfsteel.com/liuyz2006/articles/401541.html 详解JVM工作原理和特?/h1>
在我们运行和调试JavaE序的时?l常会提C个JVM的概c本文将为大家讲解JVM工作原理和特点,希望对大家有所帮助?/div>
JVM工作原理和特点主要是指操作系l装入JVM是通过jdk中Java.exe来完?通过下面4步来完成JVM环境.
1.创徏JVM装蝲环境和配|?
2.装蝲JVM.dll
3.初始化JVM.dllq挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装蝲q处理classcR?
在我们运行和调试JavaE序的时?l常会提C个JVM的概?JVM是JavaE序q行的环?但是他同时一个操作系l的一个应用程序一个进E?因此他也有他自己的运行的生命周期,也有自己的代码和数据I间.
首先来说一下JVM工作原理中的jdkq个东西,不管你是初学者还是高?是j2eeE序员还是j2seE序?jdkL在帮我们做一些事?我们在了解Java之前首先大师们会l我们提供说jdkq个东西.它在Java整个体系中充当着什么角色呢?我很惊叹sun大师们设计天?能把一个如此完整的体系l构化的如此完美.jdk在这个体pM充当一个生产加工中?产生所有的数据输出,是所有指令和战略的执行中?本n它提供了Java的完整方?可以开发目前Java能支持的所有应用和pȝE序.q里说一个问?大家会问,那ؓ什么还有j2me,j2eeq些东西,q两个东西目的很?分别用来化各自领域内的开发和构徏q程.jdk除了JVM之外,q有一些核心的API,集成API,用户工具,开发技?开发工具和API{组?
好了,废话说了那么?来点于主题相关的东西?JVM在整个jdk中处于最底层,负责于操作系l的交互,用来屏蔽操作pȝ环境,提供一个完整的Javaq行环境,因此也就虚拟计算? 操作pȝ装入JVM是通过jdk中Java.exe来完?通过下面4步来完成JVM环境.
1.创徏JVM装蝲环境和配|?
2.装蝲JVM.dll
3.初始化JVM.dllq挂界到JNIENV(JNI调用接口)实例
4.调用JNIEnv实例装蝲q处理classcR?
一QJVM装入环境QJVM提供的方式是操作pȝ的动态连接文Ӟ 既然是文仉׃个装入\径的问题QJava是怎么找这个\径的呢?当你在调用Java test的时候,操作pȝ会在path下在你的Java.exeE序QJava.exe通过下面一个过E来定JVM的\径和相关的参数配|了Q下面基于Windows的实现的分析Q?
首先查找jre路径QJava是通过GetApplicationHome api来获得当前的Java.exel对路径Qc:\j2sdk1.4.2_09\bin\Java.exe,那么它会截取到绝对\径c:\j2sdk1.4.2_09\Q判断c:\j2sdk1.4.2_09\bin\Java.dll文g是否存在Q如果存在就把c:\j2sdk1.4.2_09\作ؓjre路径Q如果不存在则判断c:\j2sdk1.4.2_09\jre\bin\Java.dll是否存在Q如果存在这c:\j2sdk1.4.2_09\jre作ؓjre路径Q如果不存在调用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本?#8221;\JavaHome的\径ؓjre路径?
然后装蝲JVM.cfg文gJRE路径+\lib+\ARCHQCPU构架Q?\JVM.cfgARCHQCPU构架Q的判断是通过Java_md.c中GetArch函数判断的,该函Cwindowsq_只有两种情况QWIN64?#8216;ia64’Q其他情况都?#8216;i386’。以我的ZQC:\j2sdk1.4.2_09\jre\lib\i386\JVM.cfg.主要的内容如下:
-client KNOWN -server KNOWN -hotspot ALIASED_TO -client -classic WARN -native ERROR -green ERROR
在我们的jdk目录中jre\bin\server和jre\bin\client都有JVM.dll文g存在Q而Java正是通过JVM.cfg配置文g来管理这些不同版本的JVM.dll的.通过文g我们可以定义目前jdk中支持那些JVM,前面部分QclientQ是JVM名称Q后面是参数QKNOWN表示JVM存在QALIASED_TO表示l别的JVM取一个别名,WARN表示不存在时找一个JVM替代QERROR表示不存在抛出异常.在运行Java XXX是,Java.exe会通过CheckJVMType来检查当前的JVMcdQJava可以通过两种参数的方式来指定具体的JVMcdQ一U按照JVM.cfg文g中的JVM名称指定Q第二种Ҏ是直接指定,它们执行的方法分别是“Java -J”?#8220;Java -XXaltJVM=”?#8220;Java -J-XXaltJVM=”。如果是W一U参C递方式,CheckJVMType函数会取参数‘-J’后面的JVM名称Q然后从已知的JVM配置参数中查扑֦果找到同名的则去掉该JVM名称前的‘-’直接q回该|而第二种ҎQ会直接q回“-XXaltJVM=”?#8220;-J-XXaltJVM=”后面的JVMcd名称Q如果在q行Java时未指定上面两种Ҏ中的M一U参敎ͼCheckJVMType会取配置文g中第一个配|中的JVM名称Q去掉名U前面的‘-’q回该倹{CheckJVMType函数的这个返回g在下面的函数中汇同jre路径l合成JVM.dll的绝对\径。如果没有指定这会用JVM.cfg中第一个定义的JVM.可以通过set _Java_LAUNCHER_DEBUG=1在控制台上测试.
最后获得JVM.dll的\径,JRE路径+\bin+\JVMcd字符?\JVM.dll是JVM的文件\径了Q但是如果在调用JavaE序时用-XXaltJVM=参数指定的\径path,q接用path+\JVM.dll文g做ؓJVM.dll的文件\径.
二:装蝲JVM.dll
通过W一步已l找CJVM的\径,Java通过LoadJavaVM来装入JVM.dll文gQ装入工作很单就是调用Windows API函数Q?
LoadLibrary装蝲JVM.dll动态连接库Q然后把JVM.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。JVM.dll的装载工作宣告完成?
三:初始化JVMQ获得本地调用接口, q样可以在Java中调用JVM的函CQ调用InvocationFunctionsQ?gt;CreateJavaVM也就是JVM中JNI_CreateJavaVMҎ获得JNIEnvl构的实例.
四:q行JavaE序Q?/strong>
JavaE序有两U方式一U是jar包,一U是class. q行jar,Java -jar XXX.jarq行的时候,Java.exe调用GetMainClassName函数Q该函数先获得JNIEnv实例然后调用JavacJava.util.jar.JarFileJNIEnv中方法getManifest()q从q回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文gQMETA-INF/MANIFEST.MF指定的Main-Class的主cd作ؓq行的主cR之后main函数会调用Java.c中LoadClassҎ装蝲该主c(使用JNIEnv实例的FindClassQ。main函数直接调用Java.c中LoadClassҎ装蝲该类。如果是执行classҎ。main函数直接调用Java.c中LoadClassҎ装蝲该类?
然后main函数调用JNIEnv实例的GetStaticMethodIDҎ查找装蝲的classȝ?
“public static void main(String[] args)”ҎQƈ判断该方法是否ؓpublicҎQ然后调用JNIEnv实例?
CallStaticVoidMethodҎ调用该JavacȝmainҎ?nbsp;
JVM工作原理和特点介l到q里?/p>
]]>
深入Java虚拟机:JVM中的Stack和Heap(转) http://www.aygfsteel.com/liuyz2006/articles/401540.html阿?/dc:creator>阿?/author>Sat, 13 Jul 2013 15:00:00 GMT http://www.aygfsteel.com/liuyz2006/articles/401540.html 深入Java虚拟机:JVM中的Stack和Heap
在JVM中,静态属性保存在Stack指o内存区,动态属性保存在Heap数据内存区。本文将从JVM的角度来讲解Java虚拟机的q一机制?/div>
在JVM中,内存分ؓ两个部分QStackQ栈Q和HeapQ堆Q,q里Q我们从JVM的内存管理原理的角度来认识Stack和HeapQƈ通过q些原理认清Java中静态方法和静态属性的问题?/p>
一般,JVM 的内存分Z部分QStack和Heap?/p>
Stack Q栈Q是JVM的内存指令区。Stack理很简单,push一定长度字节的数据或者指令,Stack指针压栈相应的字节位U;pop一定字节长度数据或者指令,Stack指针Ҏ。Stack的速度很快Q管理很单,q且每次操作的数据或者指令字节长度是已知的。所以Java 基本数据cdQJava 指o代码Q常量都保存在Stack中?/p>
Heap Q堆Q是JVM的内存数据区。Heap 的管理很复杂Q每ơ分配不定长的内存空_专门用来保存对象的实例。在Heap 中分配一定的内存来保存对象实例,实际上也只是保存对象实例的属性|属性的cd和对象本w的cd标记{,q不保存对象的方法(Ҏ是指令,保存在Stack中),在Heap 中分配一定的内存保存对象实例和对象的序列化比较类伹{而对象实例在Heap 中分配好以后Q需要在Stack中保存一?字节的Heap 内存地址Q用来定位该对象实例在Heap 中的位置Q便于找到该对象实例?/p>
׃Stack的内存管理是序分配的,而且定长Q不存在内存回收问题Q而Heap 则是随机分配内存Q不定长度,存在内存分配和回收的问题Q因此在JVM中另有一个GCq程Q定期扫描Heap Q它ҎStack中保存的4字节对象地址扫描Heap Q定位Heap 中这些对象,q行一些优化(例如合ƈI闲内存块什么的Q,q且假设Heap 中没有扫描到的区域都是空闲的Q统lrefreshQ实际上是把Stack中丢׃对象地址的无用对象清除了Q,q就是垃圾收集的q程Q关于垃圾收集的更深入讲解请参?1CTO之前的文章?a target="_blank">JVM内存模型及垃圾收集策略解?/a>》?/p>
JVM的体pȝ?/span>
我们首先要搞清楚的是什么是数据以及什么是指o。然后要搞清楚对象的Ҏ和对象的属性分别保存在哪里?/p>
1Q方法本w是指o的操作码部分Q保存在Stack中;
2Q方法内部变量作为指令的操作数部分,跟在指o的操作码之后Q保存在Stack中(实际上是单类型保存在Stack中,对象cd在Stack中保存地址Q在Heap 中保存|Q上q的指o操作码和指o操作数构成了完整的Java 指o?/p>
3Q对象实例包括其属性g为数据,保存在数据区Heap 中?/p>
非静态的对象属性作为对象实例的一部分保存在Heap 中,而对象实例必通过Stack中保存的地址指针才能讉K到。因此能否访问到对象实例以及它的非静态属性值完全取决于能否获得对象实例在Stack中的地址指针?/p>
非静态方法和静态方法的区别Q?
非静态方?/strong>有一个和静态方法很重大的不同:非静态方法有一个隐含的传入参数Q该参数是JVMl它的,和我们怎么写代码无养Iq个隐含的参数就是对象实例在Stack中的地址指针。因此非静态方法(在Stack中的指o代码QL可以扑ֈ自己的专用数据(在Heap 中的对象属性|。当焉静态方法也必须获得该隐含参敎ͼ因此非静态方法在调用前,必须先new一个对象实例,获得Stack中的地址指针Q否则JVM无法将隐含参数传给非静态方法?/p>
静态方?/strong>无此隐含参数Q因此也不需要new对象Q只要class文g被ClassLoader loadq入JVM的StackQ该静态方法即可被调用。当然此旉态方法是存取不到Heap 中的对象属性的?/p>
ȝ一下该q程Q当一个class文g被ClassLoader loadq入JVM后,Ҏ指o保存在Stack中,此时Heap 区没有数据。然后程序技术器开始执行指令,如果是静态方法,直接依次执行指o代码Q当然此时指令代码是不能讉KHeap 数据区的Q如果是非静态方法,׃隐含参数没有|会报错。因此在非静态方法执行前Q要先new对象Q在Heap 中分配数据,q把Stack中的地址指针交给非静态方法,q样E序技术器依次执行指oQ而指令代码此时能够访问到Heap 数据Z?/p>
静态属性和动态属?/strong>Q?/p>
前面提到对象实例以及动态属性都是保存在Heap 中的Q而Heap 必须通过Stack中的地址指针才能够被指oQ类的方法)讉K到。因此可以推断出Q静态属性是保存在Stack中的Q而不同于动态属性保存在Heap 中。正因ؓ都是在Stack中,而Stack中指令和数据都是定长的,因此很容易算出偏U量Q也因此不管什么指令(cȝҎQ,都可以访问到cȝ静态属性。也正因为静态属性被保存在Stack中,所以具有了全局属性?/p>
在JVM中,静态属性保存在Stack指o内存区,动态属性保存在Heap数据内存区?/p>
]]>
Q{QJDBC中驱动加载的q程分析Q下Q?/title> http://www.aygfsteel.com/liuyz2006/articles/400871.html阿?/dc:creator>阿?/author>Sun, 23 Jun 2013 06:13:00 GMT http://www.aygfsteel.com/liuyz2006/articles/400871.html JDBC中驱动加载的q程分析Q下Q?/span>
本篇主要用几个开源数据库的驱动讲q驱动是如何加蝲的,以及“可插?#8221;机制{?/span>
׃文章幅有限Q本文章q不是专门研I开源源代码Q因此我们仅研究那些与数据库驱动加蝲直接相关的方法。在下面的几个开源Y件的驱动中,我们主要x驱动cȝ getConnection() Ҏ?/span>
一、几个开源数据库的驱动类
以下W一个是 smallsql 中驱动类 SSDriver 的源代码Q?/span>
package smallsql.database;
import java.sql.*;
import java.util.Properties;
public class SSDriver implements Driver {
static SSDriver drv;
static {
try{
drv = new SSDriver();
java.sql.DriverManager.registerDriver(drv);
}catch(Throwable e){}
}
public Connection connect(String url, Properties info) throws SQLException {
if(!acceptsURL(url)) return null;
……
return new SSConnection( (idx > 0) ? url.substring(idx+1) : null);
}
……
}
从上面红色的部分可以看到Q这是一个静态语句块Q?/span>static block Q,q意味着该语句是在类构造完成前完成的(关于语句块的加蝲请阅诅R?/span>Think in java 》)。即调用 class.forName(“smallsql.database.SSDriver”) 语句Ӟ会首先创Z?/span>SSDriver 的实例,q且其向驱动管理器 (DriverManager) 注册。这样就完成驱动的注册了?/span>
从上面的蓝色的代码可以看出:驱动的连接方法返回的是一个具体的 SSConnection 对象。而在前面研究?/span>Driver 接口中返回的?/span>Connection 接口Q这是不茅盾的, SSConnection 对象实现?/span>Connection 接口?/span>
再下面一个是 HSqlD 中的驱动cȝ源代码:
package org.hsqldb;
import java.sql.*;
import java.util.Properties;
import org.hsqldb.jdbc.jdbcConnection;
import org.hsqldb.persist.HsqlDatabaseProperties;
import org.hsqldb.persist.HsqlProperties;
public class jdbcDriver implements Driver {
public Connection connect(String url, Properties info) throws SQLException {
return getConnection(url, info);
}
public static Connection getConnection(String url, Properties info) throws SQLException {
HsqlProperties props = DatabaseURL.parseURL(url, true);
if (props == null) {
throw new SQLException(Trace.getMessage(Trace.INVALID_JDBC_ARGUMENT));
} else if (props.isEmpty()) {
return null;
}
props.addProperties(info);
return new jdbcConnection(props);
}
static {
try {
DriverManager.registerDriver(new jdbcDriver());
} catch (Exception e) {}
}
}
蓝色的依然是建立q接的部分,依然q回某个具体的实?/span>java.sql.Connection接口的对象。是设计模式中的哪个工厂啊(一般工厂、抽象工厂、工厂方法还是什么都不是啊)Q?/span>
U色的同h一个静态语句块Q同样完成该驱动的注册?/span>
两个开源数据库的驱动竟然如此相|是不是其它的׃一样呢Q看下面?/span>mckoi中的驱动c:
package com.mckoi;
public class JDBCDriver extends com.mckoi.database.jdbc.MDriver {
static {
com.mckoi.database.jdbc.MDriver.register();
}
public JDBCDriver() {
super();
// Or we could move driver registering here...
}
}
U色的部分又是完成相同的工作――在类装蝲完成前向驱动理器注册驱动,只不q这ơ是调用 MDriver?/span>registerҎ|了。那么该驱动建立q接是否也一样呢Q当然一样啦Q不信你看下面的代码Q?/span>
package com.mckoi.database.jdbc;
……
public class MDriver implements Driver {
……
private static boolean registered = false;
public synchronized static void register() {
if (registered == false) {
try {
java.sql.DriverManager.registerDriver(new MDriver());
registered = true;
}catch (SQLException e) {
e.printStackTrace();
}
}
}
public Connection connect(String url, Properties info) throws SQLException {
if (!acceptsURL(url)) { return null; }
DatabaseInterface db_interface;
int row_cache_size;
int max_row_cache_size;
……
MConnection connection = new MConnection(url, db_interface, row_cache_size, max_row_cache_size);
……
return connection;
}
}
从以上三个开源数据库驱动的源代码可以看出Q在调用 Class.forName(“XXXDriver” )Ӟ完成了将具体的驱动程序向 JDBC API中驱动管理器的注册,该注册方法在cL造完成前完成Q一般用静态语句块。在调用 DriverManager?/span>getConnectionҎӞ一般先在已注册的驱动中查找可以了解?/span>URL的驱动,然后调用该驱动的 connectҎQ从而徏立连接,q回的连接都是一个实?/span>java.sql.Connection接口的具体类。下面是该过E的时序图?/span>
二?/span>JDBC中驱动加载的时序?/span>
以上?/span>JDBC中驱动加载的时序图。时序图主要有以?/span>7个动作:
1. 客户调用 Class.forName(“XXXDriver”)加蝲驱动?/span>
2. 此时此驱动类首先在其静态语句块中初始化此驱动的实例Q?/span>
3. 再向驱动理器注册此驱动?/span>
4. 客户向驱动管理器 DriverManager调用 getConnectionҎQ?/span>
5. DriverManager调用注册到它上面的能够理解此 URL的驱动徏立一个连接,
6. 在该驱动中徏立一个连接,一般会创徏一个对应于数据库提供商?/span>XXXConnectionq接对象Q?/span>
7. 驱动向客戯回此q接对象Q不q在客户调用?/span>getConnection Ҏ中返回的Z?/span>java.sql.Connection 接口Q而具体的驱动q回一个实?/span>java.sql.Connection 接口的具体类?/span>
以上是驱动加蝲的全q程。由此过E我们可以看?/span>JDBC的其它一些特炏V?/span>
三?/span>JDBC的架?/span>
在《教你徏立简?/span>JDBCE序》一中Q讲qC一?/span>JDBC的几个步骤。通过本篇的介l,我将此程序分Z下几部分Q?/span>
上图中,蓝色的即为本章前面介l的 JDBC驱动加蝲的细节部分。看看下面的部分Q左面的很明昑Q是 java.sql包中的接口吧Q它是抽象的Q右边呢Q通过驱动理?/span>DriverManager得到的是一个实?/span>java.sql.Connection接口的具体类吧!Q不知道啊!前面不是讲过了吗Q)因此我们可以可以注意到左叛_别是抽象的和具体的。(q种抽象和具体的q接是由 java?/span>RTTI支持的,不懂可以阅读?/span>Think in java》)。在接下来的l果集的处理 rs也是抽象的吧Q?/span>
因此Q在?/span>JDBCE序Ӟ即我们使用不同数据库提供商的数据库我们只要改变驱动cȝ地址Q和具体q接?/span>URL及其用户名和密码Q其它几乎不用Q何修改,可以完成同L工作Q方便吧Q?/span>
q意味着什么呢Q我们其实是在针Ҏ象接口编E,只要知道接口的调用顺序,以及其中的主要方法,我们可以迅速学?/span>JDBC~程了!
同时Q我们只要对不同数据库提供商的驱动类使用 Class.forName(“XXXDriver”)可以加载驱动,其细节你Ҏ不用x―― JDBC Framework已经全ؓ你搞定了Q应用程序对于不同提供商的数据库是无需太多改动的,因而其?#8220;可插?#8221;的!整个 J2EE是一个高层的 API――抽象接口Q用户可以用不同的产品提供商提供的产品Q用统一?/span>APIQ从而便于程序员学习Q?/span>
谢谢大家Q到此结束!
]]> (转)JDBC中驱动加载的q程分析Q上Q?/title> http://www.aygfsteel.com/liuyz2006/articles/400870.html阿?/dc:creator>阿?/author>Sun, 23 Jun 2013 06:11:00 GMT http://www.aygfsteel.com/liuyz2006/articles/400870.html 阅读全文 ]]> JAVA 字符串编码ȝ http://www.aygfsteel.com/liuyz2006/articles/385770.html阿?/dc:creator>阿?/author>Sun, 19 Aug 2012 07:10:00 GMT http://www.aygfsteel.com/liuyz2006/articles/385770.html http://www.aygfsteel.com/liuyz2006/comments/385770.html http://www.aygfsteel.com/liuyz2006/articles/385770.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/385770.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/385770.html
String newStr = new String(oldStr.getBytes(), "UTF-8"); java中的StringcL按照unicodeq行~码的,当用String(byte[] bytes, String encoding)构造字W串Ӟencoding所指的是bytes中的数据是按照那U方式编码的Q而不是最后生的String是什么编码方式,换句话说Q是让系l把bytes中的数据由encoding~码方式转换成unicode~码。如果不指明Qbytes的编码方式将由jdkҎ操作pȝ军_? 当我们从文g中读数据Ӟ最好用InputStream方式Q然后采用String(byte[] bytes, String encoding)指明文g的编码方式。不要用Reader方式Q因为Reader方式会自动根据jdk指明的编码方式把文g内容转换成unicode ~码? 当我们从数据库中L本数据时Q采用ResultSet.getBytes()Ҏ取得字节数组Q同样采用带~码方式的字W串构造方法即可? ResultSet rs; bytep[] bytes = rs.getBytes(); String str = new String(bytes, "gb2312"); 不要采取下面的步骤? ResultSet rs; String str = rs.getString(); str = new String(str.getBytes("iso8859-1"), "gb2312"); q种~码转换方式效率底。之所以这么做的原因是QResultSet在getString()Ҏ执行Ӟ默认数据库里的数据编码方式ؓ iso8859-1。系l会把数据依照iso8859-1的编码方式{换成unicode。用str.getBytes("iso8859-1")把数据还原,然后利用new String(bytes, "gb2312")把数据从gb2312转换成unicodeQ中间多了好多步骤? 从HttpRequest中读参数Ӟ利用reqeust.setCharacterEncoding()Ҏ讄~码方式Q读出的内容是正确的了?
先说Java? JVM里面的Q何字W串资源都是UnicodeQ就是说QQ何Stringcd的数据都是Unicode~码。没有例外。既然只有一U编码,那么Q我们可以这么说QJVM里面的String是不带编码的。String相当?char[]? JVM里面?byte[] 数据是带~码的。比如,Big5QGBKQGB2312QUTF-8之类的? 一个GBK~码的byte[] 转换?StringQ其实就是从GBK~码向Unicode~码转换? 一个String转换成一个Big5~码的byte[]Q其实就是从Unicode~码向Big5~码转换? 所以,Unicode是所有编码{换的中间介质。所有的~码都有一个{换器可以转换到UnicodeQ而Unicode也可以{换到其他所有的~码。这h成了一个ȝl构? 比如Q如果d?0U编码,那么只需?10 + 10 = 20个{换器够了。如果要是两两直接{换,那么Q需要的转换器数量是一个组合数字,需?0个{换器? 一个系l的不同部分Q都有自q~码。比如,数据库,文gQJVMQ浏览器q?个部分? 在这些部分之间数据交换的地方Q就会出现编码问题。比如,数据库和JVM之间Q文件和JVM之间Q浏览器和JVM之间。这些问题的原理都是盔R的? ~码问题最Ҏ处理的地Ҏ文g和JVM之间。文件IO API带有encoding 参数Q请自行查阅? 最不容易出现编码问题的地方是数据库和JVM之间。这应该是数据库JDBCq接的基本功能。本文不专门q行讨论? 最Ҏ出问题的地方是浏览器和服务器JVM之间Q其实,代码里面的字W串更容易出问题Q不q,我已l事先声明,本文不讨Z码中的字W串~码Q。下面主要讨块浏览器和服务器JVM之间的编码问题? 我们把浏览器~码叫做 Browser_CharsetQ把JVM~码叫做JVM_CharsetQ通常{于服务器系l编码)? 当浏览器的数据过来的时候,是一个带有Browser_Charset的byte[]? 如果用户处理E序需要一个Stringcd的数据,那么JVM会好心好意地把这个byte[]转换成String。用的转换器是 JVM_Charset -> Unicode? 注意Q如果这个时候,Browser_Charset ?JVM_Charsetq不相等。那么,q个自动转换是错误的? Z弥补q个错误。我们需要做两步工作? (1) Unicode -> JVM_CharsetQ把q个String 转换回到原来?byte[]? (2) Browser_Charset -> UnicodeQ把q个q原的byte[]转换?String? q个效果Q和直接从HTTP Request取得byte[]Q然后执?(2) Browser_Charset -> Unicode 的效果是一L? 如果在Request里面讄了CharacterEncodingQ那么POST Data参数׃需要自己手工{换了Qweb server的自动{换就是正的。URL的参数编码还涉及到URL~码Q需要考虑的问题多一些,没有q么单? JVM把数据发到浏览器的时候。也需要考虑~码问题。可以在Response里面讄。另外,HTML Meta Header里面也可以设|编码,提醒Browser选择正确~码? 有些语言的VM或者解释器的字W串~码可能不同。比如,Ruby。不q,~码转换原理都是一L? That is all.
JAVA字符~码 一、概? 在JAVA应用E序特别是基于WEB的程序中Q经帔R到字W的~码问题。ؓ了防止出Cؕ码,首先需要了解JAVA是如何处理字W的Q这样就可以有目的地在输?输出环节中增加必要的转码。其ơ,׃各种服务器有不同的处理方式,q需要多做试验,保使用中不出现q? 二、基本概? 2Q? JAVA中字W的表达 JAVA 中有char、byte、Stringq几个概cchar 指的是一个UNICODE字符Qؓ16位的整数。byte 是字节,字符串在|络传输或存储前需要{换ؓbyte数组。在从网l接收或从存储设备读取后需要将byte数组转换成String。String是字W串Q可以看成是由charl成的数l。String ?char 为内存Ş式,byte是网l传输或存储的序列化形式? 举例Q? ? String ying = “?#8221;; char ying = ying.charAt(0); String yingHex = Integer.toHexString(ying); 82 F1 byte yingGBBytes = ying.getBytes(“GBK”); GB~码的字节数? D3 A2 2Q? ~码方式的简? String序列化成byte数组或反序列化时需要选择正确的编码方式。如果编码方式不正确Q就会得C?x3F的倹{常用的字符~码方式有ISO8859_1、GB2312、GBK、UTF-8/UTF-16/UTF-32? ISO8859_1用来~码拉丁文,它由单字节(0Q?55Q组成? GB2312、GBK用来~码体中文,它有单字节和双字节合组成。最高位?的字节和下一个字节构成一个汉字,最高位?的字节是ASCII码? UTF-8/UTF-16/UTF-32是国际标准UNICODE的编码方式?用得最多的是UTF-8Q主要是因ؓ它在Ҏ丁文~码时节U空间? UNICODE?UTF-8~码 U-00000000 - U-0000007F: 0xxxxxxx U-00000080 - U-000007FF: 110xxxxx 10xxxxxx U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 三、J2SE中相关的函数 String str =”?#8221;; //取得GB2312~码的字? byte[] bytesGB2312 = str.getBytes(“GB2312”); //取得q_~省~码的字?solaris为ISO8859_1,windows为GB2312) byte[] bytesDefault = str.getBytes(); //用指定的~码字节{换成字符? String newStrGB = new String(bytesGB2312, “GB2312”); //用^台缺省的~码字节{换成字符?solaris为ISO8859_1,windows为GB2312) String newStrDefault = new String(bytesDefault); //用指定的~码从字节流里面d字符 InputStream in = xxx; InputStreamReader reader = InputStreamReader( in, “GB2312”); char aChar = reader.read(); 四、JSP、数据库的编? 4Q? JSP中的~码 (1) 静态声? CHARSET有两个作用: JSP文g的编码方式:在读取JSP文g、生成JAVAcLQ源JSP文g中汉字的~码 JSP输出的~码方式Q在执行JSPӞ往response里面写入数据的~码方式 (2) 动态改?在往response里面写数据前可以调用response.setContentType()Q设定正的~码cd? (3) 在TOMCAT中,由Request.getParameter() 得到的参敎ͼ~码方式都是ISO8859_1。所以如果在览器输入框内输入一个汉?#8220;?#8221;Q在服务器端得C个ISO8859_1~码的(0x00,0xD3,0x00,0xA2Q。所以通常在接收参数时转码Q? String wrongStr = response.getParameter(“name”); String correctStr = new String(wrongStr.getBytes(“ISO8859_1”),”GB2312”); 在最新的SERVLET规范里面Q也可以在获取参C前执行如下代码: request.setCharacterEncoding(“GB2312”); 4Q? 数据库的~码 (1) 数据库用UTF-16 如果String中是UNICODE字符Q写入读出时不需要{? (2) 数据库用ISO8859_1 如果String中是UNICODE字符Q写入读出时需要{? 写入QString newStr = new String(oldStr.getByte(“GB2312”), “ISO8859_1”); dQString newStr = new String(oldStr.getByte(“ISO8859_1”),”GB2312”); 五、源文g的编? 5Q? 资源文g 资源文g的编码方式和~辑q_相关。在WINDOWSq_下编写的资源文gQ以GB2312方式~码。在~译旉要{码,以确保在各个q_上的正确性: native2ascii ?encoding GB2312 source.properties q样从资源文件中d的就是正的UNICODE字符丌Ӏ? 5Q? 源文? 源文件的~码方式和编辑^台相兟뀂在WINDOWSq_下开发的源文Ӟ以GB2312方式~码。在~译的时候,需要指定源文g的编码方式: javac ?encoding GB2312 JAVA~译后生成的字节文g的编码ؓUTF-8? ①最新版TOMCAT4.1.18支持request.setCharacterEncoding(String enc) ②资源文g转码成company.name=u82f1u65afu514b ③如果数据库用utf-16则不需要这部分转码 ④面上应? 转码?: String s = new String (request.getParameter(“name”).getBytes(“ISO8859_1”),”GB2312”); 转码?: String s = new String(name.getBytes(“GB2312”),”ISO8859_1”); 转码?: String s = new String(name.getBytes(“ISO8859_1”),” GB2312”);
]]> Java几种常见的编码格? http://www.aygfsteel.com/liuyz2006/articles/385768.html阿?/dc:creator>阿?/author>Sun, 19 Aug 2012 06:38:00 GMT http://www.aygfsteel.com/liuyz2006/articles/385768.html http://www.aygfsteel.com/liuyz2006/comments/385768.html http://www.aygfsteel.com/liuyz2006/articles/385768.html#Feedback 2 http://www.aygfsteel.com/liuyz2006/comments/commentRss/385768.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/385768.html Javal合 几种常见的编码格? Z么要~码 不知道大家有没有惌一个问题,那就是ؓ什么要~码Q我们能不能不编码?要回{这个问题必要回到计算机是如何表示我们人类能够理解的符LQ这些符号也是我们人类使用的语a。由于hcȝ语言有太多,因而表C些语a的符号太多,无法用计机中一个基本的存储单元—— byte 来表C,因而必要l过拆分或一些翻译工作,才能让计机能理解。我们可以把计算够理解的语言假定语,其它语言要能够在计算Z使用必须l过一ơ翻译,把它译成英语。这个翻译的q程是~码。所以可以想象只要不是说p的国家要能够使用计算机就必须要经q编码。这看v来有些霸道,但是q就是现Ӟq也和我们国家现在在大力推广汉语一P希望其它国家都会说汉语,以后其它的语a都翻译成汉语Q我们可以把计算Z存储信息的最单位改成汉字,q样我们׃存在~码问题了? 所以ȝ来说Q编码的原因可以ȝ为: 计算Z存储信息的最单元是一个字节即 8 ?bitQ所以能表示的字W范围是 0~255 ? 人类要表C的W号太多Q无法用一个字节来完全表示 要解册个矛监ֿ需要一个新的数据结?charQ从 char ?byte 必须~码 如何“译” 明白了各U语a需要交,l过译是必要的Q那又如何来译呢?计算中提׃多种译方式Q常见的?ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16 {。它们都可以被看作ؓ字典Q它们规定了转化的规则,按照q个规则可以让计算机正的表示我们的字W。目前的~码格式很多Q例?GB2312、GBK、UTF-8、UTF-16 q几U格式都可以表示一个汉字,那我们到底选择哪种~码格式来存储汉字呢Q这p考虑到其它因素了Q是存储I间重要q是~码的效率重要。根据这些因素来正确选择~码格式Q下面简要介l一下这几种~码格式? ASCII ? 学过计算机的人都知道 ASCII 码,d?128 个,用一个字节的?7 位表C,0~31 是控制字W如换行回R删除{;32~126 是打印字W,可以通过键盘输入q且能够昄出来? ISO-8859-1 128 个字W显然是不够用的Q于?ISO l织?ASCII 码基上又制定了一些列标准用来扩展 ASCII ~码Q它们是 ISO-8859-1~ISO-8859-15Q其?ISO-8859-1 늛了大多数西欧语言字符Q所有应用的最q泛。ISO-8859-1 仍然是单字节~码Q它d能表C?256 个字W? GB2312 它的全称是《信息交换用汉字~码字符?基本集》,它是双字节编码,ȝ~码范围?A1-F7Q其中从 A1-A9 是符号区Qd包含 682 个符P?B0-F7 是汉字区Q包?6763 个汉字? GBK 全称叫《汉字内码扩展规范》,是国家技术监督局?windows95 所制定的新的汉字内码规范,它的出现是ؓ了扩?GB2312Q加入更多的汉字Q它的编码范围是 8140~FEFEQ去?XX7FQd?23940 个码位,它能表示 21003 个汉字,它的~码是和 GB2312 兼容的,也就是说?GB2312 ~码的汉字可以用 GBK 来解码,q且不会有ؕ码? GB18030 全称是《信息交换用汉字~码字符集》,是我国的强制标准Q它可能是单字节、双字节或者四字节~码Q它的编码与 GB2312 ~码兼容Q这个虽然是国家标准Q但是实际应用系l中使用的ƈ不广泛? UTF-16 说到 UTF 必须要提?UnicodeQUniversal Code l一码)QISO 试图惛_Z个全新的语a字典Q世界上所有的语言都可以通过q本字典来相互翻译。可惌知q个字典是多么的复杂Q关?Unicode 的详l规范可以参考相应文档。Unicode ?Java ?XML 的基Q下面详l介l?Unicode 在计机中的存储形式? UTF-16 具体定义?Unicode 字符在计机中存取方法。UTF-16 用两个字节来表示 Unicode 转化格式Q这个是定长的表C方法,不论什么字W都可以用两个字节表C,两个字节?16 ?bitQ所以叫 UTF-16。UTF-16 表示字符非常方便Q每两个字节表示一个字W,q个在字W串操作时就大大化了操作Q这也是 Java ?UTF-16 作ؓ内存的字W存储格式的一个很重要的原因? UTF-8 UTF-16 l一采用两个字节表示一个字W,虽然在表CZ非常单方便,但是也有其缺点,有很大一部分字符用一个字节就可以表示的现在要两个字节表示Q存储空间放大了一倍,在现在的|络带宽q非常有限的今天Q这样会增大|络传输的流量,而且也没必要。?UTF-8 采用了一U变长技术,每个~码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成? UTF-8 有以下编码规则: 如果一个字节,最高位Q第 8 位)?0Q表C是一?ASCII 字符Q?0 - 7FQ。可见,所?ASCII ~码已经?UTF-8 了? 如果一个字节,?11 开_q箋?1 的个数暗C个字W的字节敎ͼ例如Q?10xxxxx 代表它是双字?UTF-8 字符的首字节? 如果一个字节,?10 开始,表示它不是首字节Q需要向前查找才能得到当前字W的首字? Java 中需要编码的场景 前面描述了常见的几种~码格式Q下面将介绍 Java 中如何处理对~码的支持,什么场合中需要编码? I/O 操作中存在的~码 我们知道涉及到编码的地方一般都在字W到字节或者字节到字符的{换上Q而需要这U{换的场景主要是在 I/O 的时候,q个 I/O 包括盘 I/O 和网l?I/OQ关于网l?I/O 部分在后面将主要?Web 应用Z介绍。下图是 Java 中处?I/O 问题的接口: Reader cL Java ?I/O 中读字符的父c,?InputStream cLd节的父类QInputStreamReader cd是关联字节到字符的桥梁,它负责在 I/O q程中处理读取字节到字符的{换,而具体字节到字符的解码实现它?StreamDecoder d玎ͼ?StreamDecoder 解码q程中必ȝ用户指定 Charset ~码格式。值得注意的是如果你没有指?CharsetQ将使用本地环境中的默认字符集,例如在中文环境中?GBK ~码? 写的情况也是cMQ字W的父类?WriterQ字节的父类?OutputStreamQ通过 OutputStreamWriter 转换字符到字节。如下图所C: 同样 StreamEncoder c负责将字符~码成字节,~码格式和默认编码规则与解码是一致的? 如下面一D代码,实现了文件的d功能Q?
String file = "c:/stream.txt" ; String charset = "UTF-8" ; FileOutputStream outputStream = new FileOutputStream(file); OutputStreamWriter writer = new OutputStreamWriter( outputStream, charset); try { writer.write( "q是要保存的中文字符" ); } finally { writer.close(); } FileInputStream inputStream = new FileInputStream(file); InputStreamReader reader = new InputStreamReader( inputStream, charset); StringBuffer buffer = new StringBuffer(); char [] buf = new char [ 64 ]; int count = 0 ; try { while ((count = reader.read(buf)) != - 1 ) { buffer.append(buffer, 0 , count); } } finally { reader.close(); } String file = "c:/stream.txt";
String charset = "UTF-8";
// 写字W换转成字节?
FileOutputStream outputStream = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(
outputStream, charset);
try {
writer.write("q是要保存的中文字符");
} finally {
writer.close();
}
// d字节转换成字W?
FileInputStream inputStream = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(
inputStream, charset);
StringBuffer buffer = new StringBuffer();
char[] buf = new char[64];
int count = 0;
try {
while ((count = reader.read(buf)) != -1) {
buffer.append(buffer, 0, count);
}
} finally {
reader.close();
} 在我们的应用E序中涉及到 I/O 操作时只要注意指定统一的编解码 Charset 字符集,一般不会出Cؕ码问题,有些应用E序如果不注意指定字W编码,中文环境中取操作pȝ默认~码Q如果编解码都在中文环境中,通常也没问题Q但是还是强烈的不徏议用操作系l的默认~码Q因P你的应用E序的编码格式就和运行环境绑定v来了Q在跨环境下很可能出Cؕ码问题? 内存中操作中的编? ?Java 开发中除了 I/O 涉及到编码外Q最常用的应该就是在内存中进行字W到字节的数据类型的转换QJava 中用 String 表示字符Ԍ所?String cd提供转换到字节的ҎQ也支持字节{换ؓ字符串的构造函数。如下代码示例:
String s = "q是一D中文字W串" ; byte [] b = s.getBytes( "UTF-8" ); String n = new String(b, "UTF-8" ); String s = "q是一D中文字W串";
byte[] b = s.getBytes("UTF-8");
String n = new String(b,"UTF-8"); 另外一个是已经被被废弃?ByteToCharConverter ?CharToByteConverter c,它们分别提供?convertAll Ҏ可以实现 byte[] ?char[] 的互转。如下代码所C:
ByteToCharConverter charConverter = ByteToCharConverter.getConverter( "UTF-8" ); char c[] = charConverter.convertAll(byteArray); CharToByteConverter byteConverter = CharToByteConverter.getConverter( "UTF-8" ); byte [] b = byteConverter.convertAll(c); ByteToCharConverter charConverter = ByteToCharConverter.getConverter("UTF-8");
char c[] = charConverter.convertAll(byteArray);
CharToByteConverter byteConverter = CharToByteConverter.getConverter("UTF-8");
byte[] b = byteConverter.convertAll(c); q两个类已经?Charset cd代,Charset 提供 encode ?decode 分别对应 char[] ?byte[] 的编码和 byte[] ?char[] 的解码。如下代码所C:
Charset charset = Charset.forName( "UTF-8" ); ByteBuffer byteBuffer = charset.encode(string); CharBuffer charBuffer = charset.decode(byteBuffer); Charset charset = Charset.forName("UTF-8");
ByteBuffer byteBuffer = charset.encode(string);
CharBuffer charBuffer = charset.decode(byteBuffer); ~码与解码都在一个类中完成,通过 forName 讄~解码字W集Q这hҎl一~码格式Q比 ByteToCharConverter ?CharToByteConverter cL方便? Java 中还有一?ByteBuffer c,它提供一U?char ?byte 之间的Y转换Q它们之间{换不需要编码与解码Q只是把一?16bit ?char 格式Q拆分成?2 ?8bit ?byte 表示Q它们的实际值ƈ没有被修改,仅仅是数据的cd做了转换。如下代码所以:
ByteBuffer heapByteBuffer = ByteBuffer.allocate( 1024 ); ByteBuffer byteBuffer = heapByteBuffer.putChar(c); ByteBuffer heapByteBuffer = ByteBuffer.allocate(1024);
ByteBuffer byteBuffer = heapByteBuffer.putChar(c); 以上q些提供字符和字节之间的怺转换只要我们讄~解码格式统一一般都不会出现问题? Java 中如何编解码 前面介绍了几U常见的~码格式Q这里将以实际例子介l?Java 中如何实现编码及解码Q下面我们以“I am 君山”q个字符串ؓ例介l?Java 中如何把它以 ISO-8859-1、GB2312、GBK、UTF-16、UTF-8 ~码格式q行~码的?
public static void encode() { String name = "I am 君山" ; toHex(name.toCharArray()); try { byte [] iso8859 = name.getBytes( "ISO-8859-1" ); toHex(iso8859); byte [] gb2312 = name.getBytes( "GB2312" ); toHex(gb2312); byte [] gbk = name.getBytes( "GBK" ); toHex(gbk); byte [] utf16 = name.getBytes( "UTF-16" ); toHex(utf16); byte [] utf8 = name.getBytes( "UTF-8" ); toHex(utf8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public static void encode() {
String name = "I am 君山";
toHex(name.toCharArray());
try {
byte[] iso8859 = name.getBytes("ISO-8859-1");
toHex(iso8859);
byte[] gb2312 = name.getBytes("GB2312");
toHex(gb2312);
byte[] gbk = name.getBytes("GBK");
toHex(gbk);
byte[] utf16 = name.getBytes("UTF-16");
toHex(utf16);
byte[] utf8 = name.getBytes("UTF-8");
toHex(utf8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
我们?name 字符串按照前面说的几U编码格式进行编码{化成 byte 数组Q然后以 16 q制输出Q我们先看一?Java 是如何进行编码的? 下面?Java 中编码需要用到的cd ?1. Java ~码cd 首先Ҏ指定?charsetName 通过 Charset.forName(charsetName) 讄 Charset c,然后Ҏ Charset 创徏 CharsetEncoder 对象Q再调用 CharsetEncoder.encode 对字W串q行~码Q不同的~码cd都会对应C个类中,实际的编码过E是在这些类中完成的。下面是 String. getBytes(charsetName) ~码q程的时序图 ?2.Java ~码时序? 从上囑֏以看出根?charsetName 扑ֈ Charset c,然后Ҏq个字符集编码生?CharsetEncoderQ这个类是所有字W编码的父类Q针对不同的字符~码集在其子cM定义了如何实现编码,有了 CharsetEncoder 对象后就可以调用 encode Ҏd现编码了。这个是 String.getBytes ~码ҎQ其它的?StreamEncoder 中也是类似的方式。下面看看不同的字符集是如何前面的字符串编码成 byte 数组的? 如字W串“I am 君山”?char 数组?49 20 61 6d 20 541b 5c71Q下面把它按照不同的~码格式转化成相应的字节? 按照 ISO-8859-1 ~码 字符?#8220;I am 君山”?ISO-8859-1 ~码Q下面是~码l果Q? 从上囄?7 ?char 字符l过 ISO-8859-1 ~码转变?7 ?byte 数组QISO-8859-1 是单字节~码Q中?#8220;君山”被{化成值是 3f ?byte?f 也就?#8220;Q?#8221;字符Q所以经怼出现中文变成“Q?#8221;很可能就是错误的使用?ISO-8859-1 q个~码D的。中文字W经q?ISO-8859-1 ~码会丢׃息,通常我们UC?#8220;黑洞”Q它会把不认识的字符吸收掉。由于现在大部分基础?Java 框架或系l默认的字符集编码都?ISO-8859-1Q所以很Ҏ出现q问题Q后面将会分析不同的q形式是怎么出现的? 按照 GB2312 ~码 字符?#8220;I am 君山”?GB2312 ~码Q下面是~码l果Q? GB2312 对应?Charset ?sun.nio.cs.ext. EUC_CN 而对应的 CharsetDecoder ~码cL sun.nio.cs.ext. DoubleByteQGB2312 字符集有一?char ?byte 的码表,不同的字W编码就是查q个码表扑ֈ与每个字W的对应的字节,然后D?byte 数组。查表的规则如下Q?
c2b[c2bIndex[ char >> 8 ] + ( char & 0xff )] c2b[c2bIndex[char >> 8] + (char & 0xff)] 如果查到的码位值大?oxff 则是双字节,否则是单字节。双字节?8 位作为第一个字节,?8 位作为第二个字节Q如下代码所C:
if (bb > 0xff ) { if (dl - dp < 2 ) return CoderResult.OVERFLOW; da[dp++] = ( byte ) (bb >> 8 ); da[dp++] = ( byte ) bb; } else { if (dl - dp < 1 ) return CoderResult.OVERFLOW; da[dp++] = ( byte ) bb; } if (bb > 0xff) { // DoubleByte
if (dl - dp < 2)
return CoderResult.OVERFLOW;
da[dp++] = (byte) (bb >> 8);
da[dp++] = (byte) bb;
} else { // SingleByte
if (dl - dp < 1)
return CoderResult.OVERFLOW;
da[dp++] = (byte) bb;
} 从上囑֏以看出前 5 个字W经q编码后仍然?5 个字节,而汉字被~码成双字节Q在W一节中介绍?GB2312 只支?6763 个汉字,所以ƈ不是所有汉字都能够?GB2312 ~码? 按照 GBK ~码 字符?#8220;I am 君山”?GBK ~码Q下面是~码l果Q? 你可能已l发C图与 GB2312 ~码的结果是一LQ没?GBK ?GB2312 ~码l果是一LQ由此可以得?GBK ~码是兼?GB2312 ~码的,它们的编码算法也是一L。不同的是它们的码表长度不一PGBK 包含的汉字字W更多。所以只要是l过 GB2312 ~码的汉字都可以?GBK q行解码Q反q来则不然? 按照 UTF-16 ~码 字符?#8220;I am 君山”?UTF-16 ~码Q下面是~码l果Q? ?UTF-16 ~码?char 数组攑֤了一倍,单字节范围内的字W,在高位补 0 变成两个字节Q中文字W也变成两个字节。从 UTF-16 ~码规则来看Q仅仅将字符的高位和Cq行拆分变成两个字节。特Ҏ~码效率非常高,规则很简单,׃不同处理器对 2 字节处理方式不同QBig-endianQ高位字节在前,低位字节在后Q或 Little-endianQ低位字节在前,高位字节在后Q编码,所以在对一串字W串q行~码是需要指明到底是 Big-endian q是 Little-endianQ所以前面有两个字节用来保存 BYTE_ORDER_MARK |UTF-16 是用定长 16 位(2 字节Q来表示?UCS-2 ?Unicode 转换格式Q通过代理Ҏ讉K BMP 之外的字W编码? 按照 UTF-8 ~码 字符?#8220;I am 君山”?UTF-8 ~码Q下面是~码l果Q? UTF-16 虽然~码效率很高Q但是对单字节范围内字符也放大了一倍,q无形也费了存储空_另外 UTF-16 采用序~码Q不能对单个字符的编码D行校验,如果中间的一个字W码值损坏,后面的所有码值都受影响。?UTF-8 q些问题都不存在QUTF-8 对单字节范围内字W仍然用一个字节表C,Ҏ字采用三个字节表C。它的编码规则如下:
private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst){ char [] sa = src.array(); int sp = src.arrayOffset() + src.position(); int sl = src.arrayOffset() + src.limit(); byte [] da = dst.array(); int dp = dst.arrayOffset() + dst.position(); int dl = dst.arrayOffset() + dst.limit(); int dlASCII = dp + Math.min(sl - sp, dl - dp); while (dp < dlASCII && sa[sp] < '\u0080' ) da[dp++] = ( byte ) sa[sp++]; while (sp < sl) { char c = sa[sp]; if (c < 0x80 ) { if (dp >= dl) return overflow(src, sp, dst, dp); da[dp++] = ( byte )c; } else if (c < 0x800 ) { if (dl - dp < 2 ) return overflow(src, sp, dst, dp); da[dp++] = ( byte )( 0xc0 | (c >> 6 )); da[dp++] = ( byte )( 0x80 | (c & 0x3f )); } else if (Character.isSurrogate(c)) { if (sgp == null ) sgp = new Surrogate.Parser(); int uc = sgp.parse(c, sa, sp, sl); if (uc < 0 ) { updatePositions(src, sp, dst, dp); return sgp.error(); } if (dl - dp < 4 ) return overflow(src, sp, dst, dp); da[dp++] = ( byte )( 0xf0 | ((uc >> 18 ))); da[dp++] = ( byte )( 0x80 | ((uc >> 12 ) & 0x3f )); da[dp++] = ( byte )( 0x80 | ((uc >> 6 ) & 0x3f )); da[dp++] = ( byte )( 0x80 | (uc & 0x3f )); sp++; } else { if (dl - dp < 3 ) return overflow(src, sp, dst, dp); da[dp++] = ( byte )( 0xe0 | ((c >> 12 ))); da[dp++] = ( byte )( 0x80 | ((c >> 6 ) & 0x3f )); da[dp++] = ( byte )( 0x80 | (c & 0x3f )); } sp++; } updatePositions(src, sp, dst, dp); return CoderResult.UNDERFLOW; } private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst){
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
while (sp < sl) {
char c = sa[sp];
if (c < 0x80) {
// Have at most seven bits
if (dp >= dl)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
if (dl - dp < 2)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, sa, sp, sl);
if (uc < 0) {
updatePositions(src, sp, dst, dp);
return sgp.error();
}
if (dl - dp < 4)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xf0 | ((uc >> 18)));
da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
da[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (uc & 0x3f));
sp++; // 2 chars
} else {
// 3 bytes, 16 bits
if (dl - dp < 3)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xe0 | ((c >> 12)));
da[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (c & 0x3f));
}
sp++;
}
updatePositions(src, sp, dst, dp);
return CoderResult.UNDERFLOW;
} UTF-8 ~码?GBK ?GB2312 不同Q不用查码表Q所以在~码效率?UTF-8 的效率会更好Q所以在存储中文字符?UTF-8 ~码比较理想? 几种~码格式的比? 对中文字W后面四U编码格式都能处理,GB2312 ?GBK ~码规则cMQ但?GBK 范围更大Q它能处理所有汉字字W,所?GB2312 ?GBK 比较应该选择 GBK。UTF-16 ?UTF-8 都是处理 Unicode ~码Q它们的~码规则不太相同Q相Ҏ?UTF-16 ~码效率最高,字符到字节相互{换更单,q行字符串操作也更好。它适合在本地磁盘和内存之间使用Q可以进行字W和字节之间快速切换,?Java 的内存编码就是采?UTF-16 ~码。但是它不适合在网l之间传输,因ؓ|络传输Ҏ损坏字节,一旦字节流损坏很难恢复,x较而言 UTF-8 更适合|络传输Q对 ASCII 字符采用单字节存储,另外单个字符损坏也不会媄响后面其它字W,在编码效率上介于 GBK ?UTF-16 之间Q所?UTF-8 在编码效率上和编码安全性上做了qQ是理想的中文编码方式? Java Web 涉及到的~码 对于使用中文来说Q有 I/O 的地方就会涉及到~码Q前面已l提C I/O 操作会引L码,而大部分 I/O 引v的ؕ码都是网l?I/OQ因为现在几乎所有的应用E序都涉及到|络操作Q而数据经q网l传输都是以字节为单位的Q所以所有的数据都必能够被序列化ؓ字节。在 Java 中数据被序列化必ȝ?Serializable 接口? q里有一个问题,你是否认真考虑q一D|本它的实际大应该怎么计算Q我曄到q一个问题:是要想办法压羃 Cookie 大小Q减网l传输量Q当时有选择不同的压~算法,发现压羃后字W数是减了Q但是ƈ没有减少字节数。所谓的压羃只是多个单字节字符通过~码转变成一个多字节字符。减的?String.length()Q而ƈ没有减少最l的字节数。例如将“ab”两个字符通过某种~码转变成一个奇怪的字符Q虽然字W数从两个变成一个,但是如果采用 UTF-8 ~码q个奇怪的字符最后经q编码可能又会变成三个或更多的字节。同L道理比如整型数字 1234567 如果当成字符来存储,采用 UTF-8 来编码占?7 ?byteQ采?UTF-16 ~码会占用 14 ?byteQ但是把它当?int 型数字来存储只需?4 ?byte 来存储。所以看一D|本的大小Q看字符本n的长度是没有意义的,即是一L字符采用不同的编码最l存储的大小也会不同Q所以从字符到字节一定要看编码类型? 另外一个问题,你是否考虑q,当我们在电脑中某个文本编辑器里输入某个汉字时Q它到底是怎么表示的?我们知道Q计机里所有的信息都是?01 表示的,那么一个汉字,它到底是多少?0 ?1 呢?我们能够看到的汉字都是以字符形式出现的,例如?Java ?#8220;淘宝”两个字符Q它在计机中的数?10 q制?28120 ?23453Q?6 q制?6bd8 ?5d9dQ也是q两个字W是p两个数字唯一表示的。Java 中一?char ?16 ?bit 相当于两个字节,所以两个汉字用 char 表示在内存中占用相当于四个字节的I间? q两个问题搞清楚后,我们看一?Java Web 中那些地方可能会存在~码转换Q? 用户从浏览器端发起一?HTTP hQ需要存在编码的地方?URL、Cookie、Parameter。服务器端接受到 HTTP h后要解析 HTTP 协议Q其?URI、Cookie ?POST 表单参数需要解码,服务器端可能q需要读取数据库中的数据Q本地或|络中其它地方的文本文gQ这些数据都可能存在~码问题Q当 Servlet 处理完所有请求的数据后,需要将q些数据再编码通过 Socket 发送到用户h的浏览器里,再经q浏览器解码成ؓ文本。这些过E如下图所C: 如上图所CZ?HTTP h设计到很多地斚w要编解码Q它们编解码的规则是什么?下面会重点阐述一下: URL 的编解码 用户提交一?URLQ这?URL 中可能存在中文,因此需要编码,如何对这?URL q行~码Q根据什么规则来~码Q有如何来解码?如下图一?URLQ? ?4.URL 的几个组成部? 上图中以 Tomcat 作ؓ Servlet Engine ZQ它们分别对应到下面q些配置文g中: Port 对应?Tomcat ?<Connector port="8080"/> 中配|,?Context Path ?<Context path="/examples"/> 中配|,Servlet Path ?Web 应用?web.xml 中的 <servlet-mapping> <servlet-name>junshanExample</servlet-name> <url-pattern>/servlets/servlet/*</url-pattern> </servlet-mapping> <url-pattern> 中配|,PathInfo 是我们请求的具体?ServletQQueryString 是要传递的参数Q注意这里是在浏览器里直接输?URL 所以是通过 Get Ҏh的,如果?POST Ҏh的话QQueryString 通过表单方式提交到服务器端,q个在后面再介l? 上图?PathInfo ?QueryString 出现了中文,当我们在览器中直接输入q个 URL Ӟ在浏览器端和服务端会如何~码和解析这?URL 呢?Z验证览器是怎么~码 URL 的我们选择 FireFox 览器ƈ通过 HTTPFox 插g观察我们h?URL 的实际的内容Q以下是 URLQHTTP://localhost:8080/examples/servlets/servlet/ 君山 ?author= 君山在中?FireFox3.6.12 的测试结? ]]> myeclipse derby http://www.aygfsteel.com/liuyz2006/articles/382774.html阿?/dc:creator>阿?/author>Wed, 11 Jul 2012 02:08:00 GMT http://www.aygfsteel.com/liuyz2006/articles/382774.html http://www.aygfsteel.com/liuyz2006/comments/382774.html http://www.aygfsteel.com/liuyz2006/articles/382774.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/382774.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/382774.html 环境:
MyEclipse Enterprise Workbench
Version: 8.5 Build id: 8.5-20100319
WindowsXp
1.切换到数据库视图.在DB BrowserH口中找?MyEclipse Derby 单击右g选择new.
2.
Driver template: 选择derby;
Driver name: 随便比如 MyDB;
Connection URL : jdbc:derby://localhost:1527/MyDb;create=true
说明:create=true 表示创徏
Username:zhangsan Password:123456
Driver JARs:
C:/Program Files/Genuitec/MyEclipse 8.5/configuration/org.eclipse.osgi/bundles/13/1/.cp/lib/derbyclient.jar;(成功)
Driver classname = org.apache.derby.jdbc.ClientDriver
或?/p>
C:/Program Files/Genuitec/MyEclipse 8.5/configuration/org.eclipse.osgi/bundles/13/1/.cp/lib/derby.jar;(我测试没有成?
Driver class3.试一?/p>
drop table guestbook; create table guestbook (
id
int primary key generated by default as identity (START WITH 1, INCREMENT BY 1), name varchar(
20) not null, email varchar(
20), phone varchar(
20), title varchar(
50) not null, content varchar(
2000) not null, time date not
null );
insert into guestbook (id,name,email,phone,title,content,time)
values(DEFAULT,
'lala','gudong@163.com','13991736400','ok','okcontent',CURRENT DATE); select * from guestbook;
4.java中调?如果出现不能侦听1527的错?请重新启动Derby);
package webbook.chapter5;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCExample {
public static void main(String[] args) {
String driver = "org.apache.derby.jdbc.ClientDriver";
String url = "jdbc:derby://localhost:1527/MyDB";
String username = "zhangsan";
String password = "123456";
String sql = "insert into guestbook (id,name,email,phone,title,content,time)"
+"values(DEFAULT,?,?,?,?,?,CURRENT DATE)";
/*DEFAULT Derby中的自动增长 CURRENT DATE当前旉*/
Connection conn = null;
try{
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "gudong");
pstmt.setString(2, "ZhangFei@163.com");
pstmt.setString(3, "110");
pstmt.setString(4, "title");
pstmt.setString(5, "content");
pstmt.executeUpdate();
sql="select * from guestbook ";
pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
System.out.println("id:"+rs.getInt("ID"));
System.out.println("name:"+rs.getString("NAME"));
System.out.println("email:"+rs.getString("EMAIL"));
System.out.println("phone:"+rs.getString("PHONE"));
System.out.println("title:"+rs.getString("TITLE"));
System.out.println("content:"+rs.getString("content"));
System.out.println("date:"+rs.getString("time"));
}
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
-----------------------------------------
Myeclipse Derby使用指南【{?br /> 一QDerby介绍 Apache Derby是开源的Q?00% Java~写的,Ҏ理的关pL据库理pȝQ它可以和一些商业品的Ҏ进行交付?br />Apache Derby 是一个与q_无关的数据库引擎Q它?Java cd的Ş式对外提供服务。与其他难以部v的数据库不同Q安?Derby 非常单,只需要将?.jar 文g复制到系l中qؓ您的目d?.jar 文g卛_?br /> Derby拥有一个o人惊奇的Ҏ列表。它可以支持关系数据库中的所有企业的特性,包括崩溃恢复、事务回滚和提交、行/表锁、视图、主?外键U束、触发器、子查询表达式,{等。一部分的列表特性Derby从其他的Java 关系数据库管理系l中分离出来Q包括: 100% Java实现 100% Javacd4 JDBC驱动 SQL92E标准支持大部分SQL 99Ҏ?br /> ACID完全的事务独立的事务支持 J2EE支持JNDIQ连接池和XA 视图Q时表和保?br /> BLOB和CLOB数据cd 行和表锁?br /> 有h值的基本查询优化 服务器端指示U束 触发器和存储q程 为服务器端函敎ͼ触发器或存储q程{操作在数据库里存储Java代码 能排除CD-ROM里的只读数据?br /> 数据的导入和导出 快速数据库加密选项 您可以采用两U模式来部v和运行DerbyQ?br /> 在嵌入式模式Qembedded modeQ中QDerby只处理来自与应用E序使用的JVM相同的JVM的请求。在采用嵌入式模式来使用DerbyӞ应用E序会在启动和关闭时分别自动启动或停止关pd擎。Derby包的derby.jar文gQ?MBQ包含了Derby 数据库引擎和嵌入式JDBC驱动E序。嵌入式模式的主要优Ҏ不需要进行网l?和服务器讄。因Z的应用程序包含了Derby引擎Q用者ƈ不知道你使用了一个关pL据库。这点很适合我们现在桌面工具的用要求?br />在网l服务器模式Qnetwork server modeQ中QDerby会处理来自不同JVM的应用程序请求。或者,如果您喜Ƣ用Perl、PHP、Python或C来编写程序,那么您也可以部v一个Derby|络服务器,q过各种语言Ҏ的模块连接到q个服务器上Q例如Perl的DBIQDatabase InterfaceQ和PHP的ODBCQOpen Database ConnectivityQ。Derby的derbynet.jar文gQ?.2MBQ包含了Derby Network Server?br /> 另外QDerby提供了Eclipse的插件供开发h员用,下面介l插件的安装及用?br /> 二.Derby安装与?br />1.软g的下?br />你可以在Derby的官方网站下载,同时也可以下载Derby的两个Eclipse插gQderby_core_plugin和derby_ui_pluginQ在下面使用前,请安装好JVM 1.4.x或更高版本;以及Eclipse 3.x?br />2. Derby的Eclipse的插件安装与使用?br />安装插g Derby插g的安装与其他Eclipse插g安装cMQ只需要将之前下蝲的两个插件解压到Eclipse plugins目录下,然后重新启动Eclipse卛_?nbsp; Q?br />使用插g 在用该插g前,我们先创Z个Java目Q取名ؓDerbyDemoQ然后在Package Explorer视图选择该项目,单击右键选择菜单[Apache Derby]->[Add Apache Derby Nature]Q如图: 接下来是配置Derby相关属性,在Package Explorer视图选择目单击[Properties]在左边的属性列表中选择Apache DerbyQƈ?Derby 的主目录设ؓ不同于项目根目录的某个目录,例如D:/derbyDBQ如图: 配置完毕后,我们可以启动Derby服务器了Q在Package Explorer视图选择目单击[Apache Derby]->[Start Derby Network Server]Q控制台输出Derby的启动信息,启动完成?br />同样的,Derby 服务器的关闭也是cM的,在Package Explorer视图选择目单击[Apache Derby]->[Stop Derby Network Server]?br /> 2Q嵌入运行模?br /> derby.jar 和derbytools.jar导入工程 下面是连接数据库的代码片断,create=true表示创徏一个新数据?br />import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class TestDerbyBaisc { public static void main(String[] args) { try { Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();//加蝲驱动 Connection conn = DriverManager.getConnection("dbc:derby:TESTDB;create=true");//q接数据?br /> Statement st = conn.createStatement(); st.execute("create table USER_INFO (ID INT NOT NULL,NAME VARCHAR(10) NOT NULL)");// st.executeUpdate("insert into USER_INFO(ID,NAME) values (1,'hermit')");//插入数据 st.executeUpdate("insert into USER_INFO(ID,NAME) values (2,'test')");//插入数据 ResultSet rs = st.executeQuery("select * from USER_INFO");//d刚插入的数据 while(rs.next()){ int id = rs.getInt(1); String name = rs.getString(2); System.out.println("ID="+id); System.out.println("NAME="+name); } } catch(Exception e){ e.printStackTrace(); } } }
]]> eclipse的web工程转myeclipse的web工程(? http://www.aygfsteel.com/liuyz2006/articles/382480.html阿?/dc:creator>阿?/author>Sat, 07 Jul 2012 14:27:00 GMT http://www.aygfsteel.com/liuyz2006/articles/382480.html http://www.aygfsteel.com/liuyz2006/comments/382480.html http://www.aygfsteel.com/liuyz2006/articles/382480.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/382480.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/382480.html eclipse的web工程转myeclipse的web工程
1.原eclipse工程叫netschool
2.在myeclipse中新Z个工E叫netschool q在新徏的时修改 web root folder为WebContent
3.备䆾在myeclipse新徏的netschool工程下的.classpath ?mymetadata?project以及.myeclipse文g?
4.删除在myeclipse新徏的netschool工程
5.通过svn 或cvs checkout 原eclipse工程netschool 拯W三步备份的文g到netschool工程根目录下
6.h工程卛_ myeclipse的web工程转eclipse的web工程 1.先在eclipse里创Z个同名项?eg:pjt,然后pjt改名为pjt.bak. 2.从svn上check outq个目pjt?br />3.打开pjt.bak,复制.settings文g夏V?classpath?projectq个三个文g覆盖pjt目下的同名文g?/pre> ]]> java控制台程序访问oracleҎ http://www.aygfsteel.com/liuyz2006/articles/368563.html阿?/dc:creator>阿?/author>Sun, 15 Jan 2012 12:02:00 GMT http://www.aygfsteel.com/liuyz2006/articles/368563.html http://www.aygfsteel.com/liuyz2006/comments/368563.html http://www.aygfsteel.com/liuyz2006/articles/368563.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/368563.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/368563.html Ҏ1Q通过Ujava数据库驱动程?/strong> 一、java 环境变量
java_home C:\java\jdk1.6.0_30
classpath .;C:\Java\jdk1.6.0_30\lib\tool.jar;C:\Java\jdk1.6.0_26\lib\dt.jar path C:\java\jdk1.6.0_30\bin 二、把ojdbc14.jar 拯?c:\java\jre6\lib\ext?br /> 三、程?,2放于c:\下,~译生成to_oracle2.class和to_oracle22.class也在c:\ 都能成功讉K q行java to_oracle2 java to_oracle22 都能成功讉K E序1: to_oracle2.java import java.sql.*; public class to_oracle2 { static Connection conn = null; static ResultSet rs = null;
static { try{ Class.forName("oracle.jdbc.driver.OracleDriver");} catch(ClassNotFoundException e) { e.printStackTrace();} }
public static ResultSet executeQuery(String sql) { rs = null; try { conn=DriverManager.getConnection("jdbc:oracle:thin:@10.77.48.9:1521:zlj","lyz","lyz");
Statement stmt = conn.createStatement(); rs = stmt.executeQuery(sql); }catch(SQLException ex) { System.err.println("aq.executeQuery: " + ex.getMessage()); } return rs; }
public static void main (String[] args) { try { String sql="select * from work_log"; ResultSet rs1=executeQuery(sql); while (rs1.next()) {System.out.println(rs1.getString(1));} } catch (SQLException e) { } }
}
--------E序2: to_oracle22.java
import java.sql.*;
public class to_oracle22{ Connection con =null; Statement sql=null; ResultSet rs=null;
{ try{ Class.forName("oracle.jdbc.driver.OracleDriver");} catch(ClassNotFoundException e) { e.printStackTrace();}
try {con=DriverManager.getConnection("jdbc:oracle:thin:@10.77.48.9:1521:zlj","lyz","lyz");}
catch(SQLException e) { e.printStackTrace();}
}
public void query() { try{ sql=con.createStatement(); rs=sql.executeQuery("select * from work_log");
while(rs.next()) { System.out.println(rs.getString(1)); } con.close(); } catch (SQLException e) { }
} public static void main(String args[]){ to_oracle22 o= new to_oracle22(); o.query(); }
}
Ҏ2Q通过odbc数据?br /> - E序3,E序4放于c:\下,~译后的class文g也位于c:\?br />java to_oracle0 java to_oracle1 正常讉K数据?br /> E序3Qto_oracle0.java import java.sql.*; public class to_oracle0 { static String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; static String sConnStr = "jdbc:odbc:zlj"; static Connection conn = null; static ResultSet rs = null;
public to_oracle0() {
try { Class.forName(sDBDriver); } catch(java.lang.ClassNotFoundException e) { System.err.println("faq(): " + e.getMessage()); }
}
public static ResultSet executeQuery(String sql) { rs = null; try {
conn = DriverManager.getConnection(sConnStr,"lyz","lyz");
Statement stmt = conn.createStatement(); rs = stmt.executeQuery(sql); }catch(SQLException ex) { System.err.println("aq.executeQuery: " + ex.getMessage()); } return rs; }
public static void main (String[] args) { try { String sql="select * from work_log"; ResultSet rs1=executeQuery(sql); while (rs1.next()) {System.out.println(rs1.getString(1));} } catch (SQLException e) { } }
}
E序4Qto_oracle1.java import java.sql.*; public class to_oracle1 { static String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; static String sConnStr = "jdbc:odbc:zlj"; static Connection conn = null; static ResultSet rs = null;
public to_oracle1() {
try { Class.forName(sDBDriver); } catch(java.lang.ClassNotFoundException e) { System.err.println("faq(): " + e.getMessage()); }
}
public static ResultSet executeQuery(String sql) { rs = null; try {
conn = DriverManager.getConnection(sConnStr,"lyz","lyz");
Statement stmt = conn.createStatement(); rs = stmt.executeQuery(sql); }catch(SQLException ex) { System.err.println("aq.executeQuery: " + ex.getMessage()); } return rs; }
public static void main (String[] args) { try { String sql="select * from work_log"; ResultSet rs1=executeQuery(sql); while (rs1.next()) {System.out.println(rs1.getString(1));} } catch (SQLException e) { } }
}
]]> java通过JDBCq接oracle(? http://www.aygfsteel.com/liuyz2006/articles/368554.html阿?/dc:creator>阿?/author>Sun, 15 Jan 2012 07:37:00 GMT http://www.aygfsteel.com/liuyz2006/articles/368554.html http://www.aygfsteel.com/liuyz2006/comments/368554.html http://www.aygfsteel.com/liuyz2006/articles/368554.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/368554.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/368554.html java通过JDBCq接oracle
Oracle provides drivers that enable users to make JDBC connections to Oracle databases. The two most common methods of connecting to Oracle databases via JDBC are the Oracle Thin JDBC driver and the Oracle OCI JDBC driver.
The Oracle Thin driver requires no software other than the driver jar file. This driver connects to Oracle databases via TCP/IP.
The Oracle OCI (Oracle Call Interface) driver requires Oracle client software to be installed on the user’s machine in order to connect to the database. This driver uses native methods and is platform specific.
The Java classes to connect to Oracle are contained in the Oracle JDBC driver jar file. For recent releases, these are numbered based on the Java version they are compiled for, such as ojdbc14.jar (for Java 1.4), ojdbc15.jar (for Java 1.5), etc. These drivers can be freely downloaded from Oracle’s site (free registration is required).
You can tell the Oracle driver which method you wish to use to connect to the database (OCI or Thin) via the JDBC connection URL. Listed below are some example connection URL formats:
Oracle JDBC Thin Driver Formats
W一U方式:推荐使用服务名连接,Oracle JDBC Thin using a Service Name:
jdbc:oracle:thin:@//<host>:<port>/<service_name>
Example: jdbc:oracle:thin:@//192.168.2.1:1521/XE
W二U方式:适合单机的sidQOracle JDBC Thin using an SID:
jdbc:oracle:thin:@<host>:<port>:<SID>
Example: jdbc:oracle:thin:192.168.2.1:1521:X01A
Note: Support for SID is being phased out. Oracle recommends that users switch over to using service names.
Oracle JDBC Thin using a TNSName:
jdbc:oracle:thin:@<TNSName>
Example: jdbc:oracle:thin:@GL
Note: Support for TNSNames was added in the driver release 10.2.0.1
Oracle JDBC OCI Driver Format
jdbc:oracle:oci:@<database_name>
Example: jdbc:oracle:oci:@HR
The Oracle JDBC driver provides properties that can be specified when connecting to the database. Listed below are some examples of these properties.
To specify properties in the JDBC connection, you can use a Java Properties object, and pass that object into the JDBC getConnection method. For example:
java.util.Properties info = new java.util.Properties();
info.put(“internal_logon”, “sysdba”);
Connection conn = DriverManager.getConnection (url, info);
Connection Properties
internal_logon: Use this property to connect as a sysoper or sysdba role. When using this property, the user and password properties must be included in the properties object. For example:
Properties props = new Properties();
props.put(“user”, “scott”);
props.put(“password”, “tiger”);
props.put(“internal_logon”, “sysoper”);
Connection conn = DriverManager.getConnection (url, props);
defaultRowPrefetch: Oracle JDBC drivers allow you to set the number of rows to prefetch from the server while the result set is being populated during a query. Prefetching row data into the client reduces the number of round trips to the server. A typical value for this property is 10.
defaultBatchValue: Oracle JDBC drivers allow you to accumulate inserts and updates of prepared statements and send them to the server in batches once it reaches a specified batch value. This feature reduces round trips to the server. Use the value 1 if you don’t want to use this feature.
processEscapes: “false” to disable escape processing for statements (Statement or PreparedStatement) created from this connection. Set this to “false” if you want to avoid many calls to Statement.setEscapeProcessing(false);. This is espcially usefull for PreparedStatement where a call to setEscapeProcessing(false) would have no effect. The default is “true”.
No related posts.
]]> 数据的传g引用(? http://www.aygfsteel.com/liuyz2006/articles/368517.html阿?/dc:creator>阿?/author>Sat, 14 Jan 2012 14:04:00 GMT http://www.aygfsteel.com/liuyz2006/articles/368517.html http://www.aygfsteel.com/liuyz2006/comments/368517.html http://www.aygfsteel.com/liuyz2006/articles/368517.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/368517.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/368517.html
数据的传g引用(?
数据的传g引用主要体现在函数调用时候,通过参数来实现?/p>
当数据在传递时Q内存ؓ实际参数开辟内存地址及内存空_存放数据变ؓ形式参数Q非同于实际参数的内存地址和内存空_。当调用函数完后Q定义函数相应的执行q没有改变实际参数?/p>
当数据(数组在引用时Q,内存只开辟内存地址而ƈ不开辟内存空_开辟的内存地址相同Q决定了同一个地址位置。函数调用时Q实际参数在定义函数的执行过E中Q发生改变,因而成为引用。有点类g拷贝,用的是同一个地址?/p>
MQ?/p>
数据的传递,内存不仅开辟存放数据的内存地址Q还开辟存放数据的内存I间Q数据传递到定义函数时候,实际参数到Ş式参数后Q内存自动清I数据,数据在定义函数执行后不发生Q何变化;数组在引用时Q尽开辟了内存地址Qƈ没有开辟存放数据的I间Q数l在函数调用后,引用的是同一内存地址Q必然数l经q定义函数后Q实际参数发生改变?/p>
]]> java讉Koracle q回json 实践Q一Q?/title> http://www.aygfsteel.com/liuyz2006/articles/367954.html阿?/dc:creator>阿?/author>Thu, 05 Jan 2012 14:00:00 GMT http://www.aygfsteel.com/liuyz2006/articles/367954.html http://www.aygfsteel.com/liuyz2006/comments/367954.html http://www.aygfsteel.com/liuyz2006/articles/367954.html#Feedback 0 http://www.aygfsteel.com/liuyz2006/comments/commentRss/367954.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/367954.html ------------Z个javabean c?WorkRecord 用于保存讉K数据库记录的内容
public class WorkRecord { private long do_seq; private String proc_name; private String sql_desc; private String work_status;
public void setdo_seq(long do_seq) { this.do_seq=do_seq; }
public void setproc_name(String proc_name) { this.proc_name=proc_name; }
public void setsql_desc(String sql_desc) { this.sql_desc=sql_desc; }
public void setwork_status(String work_status) { this.work_status=work_status; }
public long getDo_seq() { return do_seq; }
public String getProc_name() { return proc_name; }
public String getSql_desc() { return sql_desc; }
public String getWork_status() { return work_status; }
public static void main (String[] args) { System.out.println("hello"); }
} ------------------------------Z个javabeancfaq 用于讉K数据库,q将讉K的记录存于对象WorkRecord中,多个WorkRecord存于列表?/p>
//java bean //file name: faq.java
//package Test;
import java.util.ArrayList; import java.util.List; import net.sf.json.JSON; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; //import WorkRecord;
import java.sql.*; public class faq { String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; String sConnStr = "jdbc:odbc:wz"; Connection conn = null; ResultSet rs = null; JSON json; public faq() { try { Class.forName(sDBDriver); }catch(java.lang.ClassNotFoundException e) { System.err.println("faq(): " + e.getMessage()); } }
public void executeQuery(String sql) { rs = null; try { conn = DriverManager.getConnection(sConnStr,"liuyz","liuyz1"); Statement stmt = conn.createStatement(); rs = stmt.executeQuery(sql); //List result =new ArrayList();
List<WorkRecord> result = new ArrayList<WorkRecord>();
while (rs.next()) { WorkRecord rec= new WorkRecord(); rec.setdo_seq(rs.getLong("do_seq")); rec.setproc_name(rs.getString("proc_name")); rec.setsql_desc(rs.getString("sql_desc")); rec.setwork_status(rs.getString("work_status")); result.add(rec); } //JSONObject json= JSONSerializer.toJSON(result); json = JSONSerializer.toJSON(result);
} catch(SQLException ex) { System.err.println("aq.executeQuery: " + ex.getMessage()); }
//return json.toString(); System.out.println(json.toString());
}
public static void main (String[] args) { faq aaa =new faq(); aaa.executeQuery("select * from work_log where do_seq=399252 or do_seq=399261 "); }
}
1、在c:\下解压json支持库生?org net 目录 2、在c:\下编写前面两个文?br />3、javac WorkRecord.java ; javac faq.java 4、java faq q行后返回以下json 格式的数?br /> [{"do_seq":399252,"proc_name":"LIUYZ.GET_GD\n","sql_desc":"delete from busi_log a where\nbusiness_id in (500000020057,8000100108,500000020204,800015100004,80 0015100003,800015100002,800015100008,800015100005,800015100006,800015100000,8000 100100,8000100126,500000020055,500000020053,8000000015,8000000012,800015101178,5 00000021011,800015101251,500000021012,500000020222,500000020223,500000020038,500 000020093,500000020094,360,500000020064,500000020339,500000020079,500000020009,5 00000020006,2100000003,8000100103,500000020028,500000020007,500000020012,5000000 20221,500000020220,500000020073,500000020074,8000000620,500000020320,50000002020 3,900000030001,500000020076,500000020077,8000000021,8100000987,500000020008,5000 00020096,2100000004,8000000002,8000000005)","work_status":"finished"},{"do_seq": 399261,"proc_name":"LIUYZ.GET_GD\n","sql_desc":"delete from yz_gd where fee_de tail like '%l端差h%'","work_status":"finished"}] 注://List result =new ArrayList();
List<WorkRecord> result = new ArrayList<WorkRecord>();
~译正常 如改?/span>List result =new ArrayList();
// List<WorkRecord> result = new ArrayList<WorkRecord>();
~译出现下面信息 C:\>javac faq.java 注意Qfaq.java 使用了未l检查或不安全的操作?/span>注意Q要了解详细信息Q请使用 -Xlint:unchecked 重新~译?/span>但运行正常,仍能产生json格式的数?/span>
]]>java对象生成json实例 http://www.aygfsteel.com/liuyz2006/articles/367945.html阿?/dc:creator>阿?/author>Thu, 05 Jan 2012 12:28:00 GMT http://www.aygfsteel.com/liuyz2006/articles/367945.html http://www.aygfsteel.com/liuyz2006/comments/367945.html http://www.aygfsteel.com/liuyz2006/articles/367945.html#Feedback 1 http://www.aygfsteel.com/liuyz2006/comments/commentRss/367945.html http://www.aygfsteel.com/liuyz2006/services/trackbacks/367945.html
1、不带包的用方?br /> 解压json和支持包在当前目录下生成
org
net
javac User.java
javac Test.java
java Test 输出
{"age":25,"name":"phl"}
[{"age":25,"name":"phl"},{"age":26,"name":"luckybird"}]
{"age":0,"name":""}
------------------User.java-----------------
public class User { private String name; private int age;
public String getName() { return this.name; }
public int getAge(){ return this.age;
}
public void setName(String v_name) { this.name=v_name; }
public void setAge(int v_age) { this.age=v_age; } }
---------------Test.java------------------
import java.util.ArrayList; import java.util.List; import net.sf.json.JSON; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; public class Test { public static void main(String[] args) throws Exception { User user = new User(); user.setName("phl"); user.setAge(25); User user2 = new User(); user2.setName("luckybird"); user2.setAge(26); List<User> list = new ArrayList<User>(); list.add(user); list.add(user2); JSONObject json = JSONObject.fromObject(user); System.out.println(json.toString()); // ******************************************************** JSON json2 = JSONSerializer.toJSON(list); System.out.println(json2.toString()); json2 = JSONSerializer.toJSON(new User()); System.out.println(json2.toString()); } }
===================================================================== 2、带包的使用方式
------------------User.java-----------------package nn;
public class User { private String name; private int age;
public String getName() { return this.name; }
public int getAge(){ return this.age;
}
public void setName(String v_name) { this.name=v_name; }
public void setAge(int v_age) { this.age=v_age; } }
---------------Test.java------------------ package mm;
import java.util.ArrayList; import java.util.List; import net.sf.json.JSON; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; import nn.User; public class Test { public static void main(String[] args) throws Exception { User user = new User(); user.setName("phl"); user.setAge(25); User user2 = new User(); user2.setName("luckybird"); user2.setAge(26); List<User> list = new ArrayList<User>(); list.add(user); list.add(user2); JSONObject json = JSONObject.fromObject(user); System.out.println(json.toString()); // ******************************************************** JSON json2 = JSONSerializer.toJSON(list); System.out.println(json2.toString()); json2 = JSONSerializer.toJSON(new User()); System.out.println(json2.toString()); } }
================== javac User.java ->User.class javac Test.java ->Test.class 拯User.class->nn目录?;Test.class->mm目录?br />调用方式java mm.Test {"age":25,"name":"phl"} [{"age":25,"name":"phl"},{"age":26,"name":"luckybird"}] {"age":0,"name":""}
]]>
վ֩ģ壺
|
|
|
|
¦ |
Ž |
|
|
ﶫ |
罭 |
|
|
|
ͬ |
|
Ұ |
Ĵʡ |
պ |
|
|
ʡ |
ʤ |
կ |
Ƹ |
̫ |
̨ |
|
ȫ |
|
̨ |
|
ɽ |
ʤ |
|
|
|
¡ |
ˮ |
|
|
|