舍掉小数取整:Math.floor(3.5)=3
四舍五入取整:Math.rint(3.5)=4
进位取整:Math.ceil(3.1)=4
2009年7月29日星期三
2009年4月17日星期五
Java类的写法
本文向大家介绍如何创建Java类和创建Java类的基本语法,通过一个例子来向大家介绍类的主要概念。
Public class Stack {
** Vector items;
publicd Stack() {
items = new Vector(10);
}
public Object push(Object item) {
items.addElement(item);
returen item;
}
public synchronized Object pop() {
int len = items.size();
Object obj = null;
if(len == 0) throw new EmptStackException();
obj = items.elementAt(len - 1);
items.removeElementAt(len - 1);
return obj;
}
public boolean isEmpty() {
if(items.size() == 0)
return true;
else
return false;
}
}
上面的例子定义了一个类叫作Stack,在这个类中定义了一个实例变量items,定义了一个构造器,定义了三个方法,关于实例变量,构造器和方法我们会再后面一个一个的给大家进行讲解。
类的定义:
一个类在使用前必须要进行定义,当然Java本身提供了许多类,你可以直接拿过来使用,就象C语言中预定义的许多变量一样,不用你自己定义了。类声明的语法主要包括两个部分,一个是类的声明,就是上面例子中的第一行语句,用来声明类的名称等信息;下面用一对大括号括起来的部分称为类体,用来定义类的实例对象,构造器和方法等。
类的声明:
下面我们给出类声明的语法,
public class is publicly accessible
abstract class cannot be instantiated
final class cannot be subclassed
class NameOfClass Name of the Class
extends Super Superclass of the class
implements Interfaces Interfaces implemented by the class {
ClassBody
}
上面的语法中,大括号前面的内容就是类声明的基本语法,其中Class NameOfClass是类声明中最主要的部分,它定义了类的名称,是必不可少的,Class是Java的关键字,NameOfClass是类的真实名称。public,abstract,final可看成是一组,在使用的时候只能使用其中一个,他们必须放在类的名称前面,如果使用public说明定义的这个类可以被在同一个封装中的其他类所使用和访问,如果使用abstract说明定义的这个类是一个抽象类,不能用此类来创建类的实例,也就是对象,如果使用final说明定义的类是一个终极类,不能在用这个类来定义子类了。extends Super和implements Interfaces可以看成一组,在使用的时候只能使用其中的一个,如果使用extends Super说明现在定义的类是一个超类的子类,如果使用implements Interfaces说明该类使用了Interfaces接口,这两个组成部分体现了类的继承特性。
类定义中的类体部分主要包含三个成分:实例变量,构造器和方法,这三个成分称为类的成员。其中实例变量用来保存类的状态,构造器用来对类的实例进行初始化,方法将用来赋予类强大的能力,来完成一些工作。
下面我们就组成类体的三个成分分别进行说明:
构造器:
构造器的作用就是对类的实例进行初始化。构造器的名字必须和类名称相同。比如例子中展示的类Stack的构造器也叫Stack。Java允许类可以有多个构造器,但所有的构造器名称都要相同,要和类名称相同,但每个构造器的参数数量和类型是不同。编译器会根据参数的数目和类型来准确的判断应该使用哪个构造器来对类的实例进行初始化。一般的情况下,构造器主要就是对类的实例变量进行初始化。编译器会根据你调用构造器时所使用的参数的个数和类型来选择准确的构造器。
当你编写一个类的时候,你也可以不给类定义构造器,此时Java的运行环境会自动使用默认的构造器来对类实例进行初始化。
实例变量:
在上面的例子中我们使用了一个实例变量:
** Vector items;
实例变量用来描述类的状态。注意:为了声明实例变量我们应该将上面这条语句方法类体中,但不能放在类的方法声明中。在方法中声明的变量是方法的本地变量,和我们现在提到的实例变量是不一样的。
accessLevel Indicates the access level for this member
static Declares a class member
final Indicates that it is constant
transinet This variable is transient
volatile This variable is volatile
type name The type and name of the variable
上面就是声明一个实例变量的语法成分,其中type name是声明一个实例变量必须要有的,type用来说明实例变量的数据类型,也就说明该变量可以用来存放的值的类型,name是实例变量的名称,变量名可以由任何合法的字符组成,首字符应该是一个字母。在一个类中,实例变量应该是唯一的,不能存在两个名称相同的实例变量,但你可以在该类的子类中重新定义一个实例变量和你的超类的实例变量名称相同,这时,子类的实例变量会覆盖掉超类的实例变量,另外实例变量的名称可以和类中的某个方法的名称相同。
除了type name之外,下面我们对其他的成分进行一下说明:
accessLevel
你可以使用这个修改符来控制其他类对该实例变量的访问方式,不同的访问方式包括:public,protected,package,和**。
static
声明一个类变量,这个变量在不声明类实例的情况下就可以使用,使用的方式是:对象名.变量名
final
使用这个修改符实际上上是定义了常量,他的值是不能被改变的。所以你不能在程序中去修改他的值,如果你试图这样做的话,结果将是在编译的时候发生错误。
transient
这种控制方式实际上不是Java语言主要的控制方式,主要是在serialization对象中使用。
volatile
这个修改符用来通知编译器不要在编译的时候对实例变量进行优化,这是一个Java的高级特性,一般很少用到他。
方法:
向你所知道的那样,对象有一个能力就是去执行一些方法,其他类的对象可以通过调用该类的方法来让该类执行一定的操作,下面我们就来看看如何在你的程序中给类填加方法。
public Object push(Objec item) {
items.addElement(item);
return item;
}
上面的例子定义了一个方法,通过这个例子我们可以分析一下,一个方法的定义应该包括两大部分,一个就是方法声明,一个是方法体。
方法声明用来定义类的各种性质,例如访问级别,返回类型,名称和参数等等。
accessLevel Access level for this method
static This is a class method
abstract This method is not implemented
final Method cannot be overridden
native Method implemented in another language
synchronized Method requires a monitor to run
returnType methodname The return type and method name
(paramlist) The list of arguments
throws exceptions The exceptions thrown by this method
上面就是声明一个方法的语法成分,一样其中rutuenType mehtodname是在声明一个方法的时候必须要有的,其中methodname是方法的名称。returntype是方法的返回值类型。
声明一个方法的语法中其他的成分说明如下:
accessLevel:
和声明一个实例变量时是一样的,用来控制其他类访问该方法的方式,其中包括public,protected,package,和**。
static:
用来声明一个类方法,该方法可以在不声明对象实例的情况下直接使用,使用的语法是:对象名.方法名
abstract:
用来声明一个抽象方法,该方法不能通过对象实例来直接使用,因为该方法一定是一个抽象类中的方法。
final:
声明一个终极类方法,就是说在该类的子类中不能用同名的方法来覆盖本方法。
native:
如果你有一些使用其他编程语言编写的函数,想在Java程序中使用他们,你可以使用native关键字来声明类中的某个方法不是用java编写的,这样你就可以将以往的工作成果包含到你的Java程序中。
synchronized:
当多个方法可能同时对同一个数据进行操作时,就需要对这些方法进行同步,确保每个方法的操作不会影响到其他的方法,这时你就可以使用该方法来完成。
(paramlist)
这是方法的参数,用来给方法传递信息。
[throws exceptions]
当你的程序在执行过程中可能会出现一些问题或错误的时候,你应该进行违例处理,这就是本成分的功能,具体的违例处理我们还会在其他的文章中进行说明。
在方法体中,你可以编写任何条数的语句。另外我们还要说明三个概念:
this:
在类的方法中,你可以使用this来表示对本类自身的调用,比如你在方法中需要使用到该类的某个实例变量,你可以通过this.变量名来使用。
super:
如果你的类是一个超类的子类,你可以通过在该类的方法中使用super来调用超类的方法和实例变量等。
本地变量:
你可以在方法体中声明任意数量的本地变量。这些变量是本地变量,他们的作用域只限于本方法内,当方法结束的时候,该变量的生命期就结束了。
好,最后我们再对**,public,protected,package说明一下:
在类中,声明方法和实例变量的时候都可以通过上面的四个修改符来控制他们可能被其他类访问的方式,其中:
**:
将限制方法和实例变量只能被本方法中的其他方法所访问。
protected:
则允许类的方法和实例变量可以被该类,子类和在一个Package中的其他方法所访问
public:
允许任何类来访问。
package:
则限制只有该类和在一个Package中的其他类来访问。
ok,我们通过上面的讲解,基本说明了定义一个类的基本语法成分,大家如果对这一部分的内容理解之后,我想你就可以自己利用前面提到的Java基本语法和类的基本语法来编写自己的类了!
Public class Stack {
** Vector items;
publicd Stack() {
items = new Vector(10);
}
public Object push(Object item) {
items.addElement(item);
returen item;
}
public synchronized Object pop() {
int len = items.size();
Object obj = null;
if(len == 0) throw new EmptStackException();
obj = items.elementAt(len - 1);
items.removeElementAt(len - 1);
return obj;
}
public boolean isEmpty() {
if(items.size() == 0)
return true;
else
return false;
}
}
上面的例子定义了一个类叫作Stack,在这个类中定义了一个实例变量items,定义了一个构造器,定义了三个方法,关于实例变量,构造器和方法我们会再后面一个一个的给大家进行讲解。
类的定义:
一个类在使用前必须要进行定义,当然Java本身提供了许多类,你可以直接拿过来使用,就象C语言中预定义的许多变量一样,不用你自己定义了。类声明的语法主要包括两个部分,一个是类的声明,就是上面例子中的第一行语句,用来声明类的名称等信息;下面用一对大括号括起来的部分称为类体,用来定义类的实例对象,构造器和方法等。
类的声明:
下面我们给出类声明的语法,
public class is publicly accessible
abstract class cannot be instantiated
final class cannot be subclassed
class NameOfClass Name of the Class
extends Super Superclass of the class
implements Interfaces Interfaces implemented by the class {
ClassBody
}
上面的语法中,大括号前面的内容就是类声明的基本语法,其中Class NameOfClass是类声明中最主要的部分,它定义了类的名称,是必不可少的,Class是Java的关键字,NameOfClass是类的真实名称。public,abstract,final可看成是一组,在使用的时候只能使用其中一个,他们必须放在类的名称前面,如果使用public说明定义的这个类可以被在同一个封装中的其他类所使用和访问,如果使用abstract说明定义的这个类是一个抽象类,不能用此类来创建类的实例,也就是对象,如果使用final说明定义的类是一个终极类,不能在用这个类来定义子类了。extends Super和implements Interfaces可以看成一组,在使用的时候只能使用其中的一个,如果使用extends Super说明现在定义的类是一个超类的子类,如果使用implements Interfaces说明该类使用了Interfaces接口,这两个组成部分体现了类的继承特性。
类定义中的类体部分主要包含三个成分:实例变量,构造器和方法,这三个成分称为类的成员。其中实例变量用来保存类的状态,构造器用来对类的实例进行初始化,方法将用来赋予类强大的能力,来完成一些工作。
下面我们就组成类体的三个成分分别进行说明:
构造器:
构造器的作用就是对类的实例进行初始化。构造器的名字必须和类名称相同。比如例子中展示的类Stack的构造器也叫Stack。Java允许类可以有多个构造器,但所有的构造器名称都要相同,要和类名称相同,但每个构造器的参数数量和类型是不同。编译器会根据参数的数目和类型来准确的判断应该使用哪个构造器来对类的实例进行初始化。一般的情况下,构造器主要就是对类的实例变量进行初始化。编译器会根据你调用构造器时所使用的参数的个数和类型来选择准确的构造器。
当你编写一个类的时候,你也可以不给类定义构造器,此时Java的运行环境会自动使用默认的构造器来对类实例进行初始化。
实例变量:
在上面的例子中我们使用了一个实例变量:
** Vector items;
实例变量用来描述类的状态。注意:为了声明实例变量我们应该将上面这条语句方法类体中,但不能放在类的方法声明中。在方法中声明的变量是方法的本地变量,和我们现在提到的实例变量是不一样的。
accessLevel Indicates the access level for this member
static Declares a class member
final Indicates that it is constant
transinet This variable is transient
volatile This variable is volatile
type name The type and name of the variable
上面就是声明一个实例变量的语法成分,其中type name是声明一个实例变量必须要有的,type用来说明实例变量的数据类型,也就说明该变量可以用来存放的值的类型,name是实例变量的名称,变量名可以由任何合法的字符组成,首字符应该是一个字母。在一个类中,实例变量应该是唯一的,不能存在两个名称相同的实例变量,但你可以在该类的子类中重新定义一个实例变量和你的超类的实例变量名称相同,这时,子类的实例变量会覆盖掉超类的实例变量,另外实例变量的名称可以和类中的某个方法的名称相同。
除了type name之外,下面我们对其他的成分进行一下说明:
accessLevel
你可以使用这个修改符来控制其他类对该实例变量的访问方式,不同的访问方式包括:public,protected,package,和**。
static
声明一个类变量,这个变量在不声明类实例的情况下就可以使用,使用的方式是:对象名.变量名
final
使用这个修改符实际上上是定义了常量,他的值是不能被改变的。所以你不能在程序中去修改他的值,如果你试图这样做的话,结果将是在编译的时候发生错误。
transient
这种控制方式实际上不是Java语言主要的控制方式,主要是在serialization对象中使用。
volatile
这个修改符用来通知编译器不要在编译的时候对实例变量进行优化,这是一个Java的高级特性,一般很少用到他。
方法:
向你所知道的那样,对象有一个能力就是去执行一些方法,其他类的对象可以通过调用该类的方法来让该类执行一定的操作,下面我们就来看看如何在你的程序中给类填加方法。
public Object push(Objec item) {
items.addElement(item);
return item;
}
上面的例子定义了一个方法,通过这个例子我们可以分析一下,一个方法的定义应该包括两大部分,一个就是方法声明,一个是方法体。
方法声明用来定义类的各种性质,例如访问级别,返回类型,名称和参数等等。
accessLevel Access level for this method
static This is a class method
abstract This method is not implemented
final Method cannot be overridden
native Method implemented in another language
synchronized Method requires a monitor to run
returnType methodname The return type and method name
(paramlist) The list of arguments
throws exceptions The exceptions thrown by this method
上面就是声明一个方法的语法成分,一样其中rutuenType mehtodname是在声明一个方法的时候必须要有的,其中methodname是方法的名称。returntype是方法的返回值类型。
声明一个方法的语法中其他的成分说明如下:
accessLevel:
和声明一个实例变量时是一样的,用来控制其他类访问该方法的方式,其中包括public,protected,package,和**。
static:
用来声明一个类方法,该方法可以在不声明对象实例的情况下直接使用,使用的语法是:对象名.方法名
abstract:
用来声明一个抽象方法,该方法不能通过对象实例来直接使用,因为该方法一定是一个抽象类中的方法。
final:
声明一个终极类方法,就是说在该类的子类中不能用同名的方法来覆盖本方法。
native:
如果你有一些使用其他编程语言编写的函数,想在Java程序中使用他们,你可以使用native关键字来声明类中的某个方法不是用java编写的,这样你就可以将以往的工作成果包含到你的Java程序中。
synchronized:
当多个方法可能同时对同一个数据进行操作时,就需要对这些方法进行同步,确保每个方法的操作不会影响到其他的方法,这时你就可以使用该方法来完成。
(paramlist)
这是方法的参数,用来给方法传递信息。
[throws exceptions]
当你的程序在执行过程中可能会出现一些问题或错误的时候,你应该进行违例处理,这就是本成分的功能,具体的违例处理我们还会在其他的文章中进行说明。
在方法体中,你可以编写任何条数的语句。另外我们还要说明三个概念:
this:
在类的方法中,你可以使用this来表示对本类自身的调用,比如你在方法中需要使用到该类的某个实例变量,你可以通过this.变量名来使用。
super:
如果你的类是一个超类的子类,你可以通过在该类的方法中使用super来调用超类的方法和实例变量等。
本地变量:
你可以在方法体中声明任意数量的本地变量。这些变量是本地变量,他们的作用域只限于本方法内,当方法结束的时候,该变量的生命期就结束了。
好,最后我们再对**,public,protected,package说明一下:
在类中,声明方法和实例变量的时候都可以通过上面的四个修改符来控制他们可能被其他类访问的方式,其中:
**:
将限制方法和实例变量只能被本方法中的其他方法所访问。
protected:
则允许类的方法和实例变量可以被该类,子类和在一个Package中的其他方法所访问
public:
允许任何类来访问。
package:
则限制只有该类和在一个Package中的其他类来访问。
ok,我们通过上面的讲解,基本说明了定义一个类的基本语法成分,大家如果对这一部分的内容理解之后,我想你就可以自己利用前面提到的Java基本语法和类的基本语法来编写自己的类了!
2009年4月4日星期六
JAVA中对数字证书的操作
未经实践,仅供研究参考存档用,使用者自行承担风险。
一:需要包含的包
二:从文件中读取证书
用keytool将.keystore中的证书写入文件中,然后从该文件中读取证书信息
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in=new FileInputStream("out.csr");
Certificate c=cf.generateCertificate(in);
String s=c.toString();
三:从密钥库中直接读取证书
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
java.security.cert.Certificate c=ks.getCertificate(alias);//alias为条目的别名
四:JAVA程序中显示证书指定信息
System.out.println("输出证书信息:\n"+c.toString());
System.out.println("版本号:"+t.getVersion());
System.out.println("序列号:"+t.getSerialNumber().toString(16));
System.out.println("主体名:"+t.getSubjectDN());
System.out.println("签发者:"+t.getIssuerDN());
System.out.println("有效期:"+t.getNotBefore());
System.out.println("签名算法:"+t.getSigAlgName());
byte [] sig=t.getSignature();//签名值
PublicKey pk=t.getPublicKey();
byte [] pkenc=pk.getEncoded();
System.out.println("公钥");
for(int i=0;i<pkenc.length;i++)System.out.print(pkenc[i]+",");
五:JAVA程序列出密钥库所有条目
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
Enumeration e=ks.aliases();
while(e.hasMoreElements())
java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());
六:JAVA程序修改密钥库口令
String oldpass="123456";
String newpass="654321";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,oldpass.toCharArray());
in.close();
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,newpass.toCharArray());
output.close();
七:JAVA程序修改密钥库条目的口令及添加条目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
Certificate [] cchain=ks.getCertificate(alias);获取别名对应条目的证书链
PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());获取别名对应条目的私钥
ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密钥库中添加条目
第一个参数指定所添加条目的别名,假如使用已存在别名将覆盖已存在条目,使用新别名将增加一个新条目,第二个参数为条目的私钥,第三个为设置的新口令,第四个为该私钥的公钥的证书链
FileOutputStream output=new FileOutputStream("another");
ks.store(output,storepass.toCharArray())将keystore对象内容写入新文件
八:JAVA程序检验别名和删除条目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
ks.containsAlias("sage");检验条目是否在密钥库中,存在返回true
ks.deleteEntry("sage");删除别名对应的条目
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,storepass.toCharArray())将keystore对象内容写入文件,条目删除成功
九:JAVA程序签发数字证书
(1)从密钥库中读取CA的证书
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
java.security.cert.Certificate c1=ks.getCertificate("caroot");
(2)从密钥库中读取CA的私钥
PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());
(3)从CA的证书中提取签发者的信息
byte[] encod1=c1.getEncoded(); 提取CA证书的编码
X509CertImpl cimp1=new X509CertImpl(encod1); 用该编码创建X509CertImpl类型对象
X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象
X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 获取X509Name类型的签发者信息
(4)获取待签发的证书
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("user.csr");
java.security.cert.Certificate c2=cf.generateCertificate(in);
(5)从待签发的证书中提取证书信息
byte [] encod2=c2.getEncoded();
X509CertImpl cimp2=new X509CertImpl(encod2); 用该编码创建X509CertImpl类型对象
X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象
(6)设置新证书有效期
Date begindate=new Date(); 获取当前时间
Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期为3000天
CertificateValidity cv=new CertificateValidity(begindate,enddate); 创建对象
cinfo2.set(X509CertInfo.VALIDITY,cv); 设置有效期
(7)设置新证书序列号
int sn=(int)(begindate.getTime()/1000); 以当前时间为序列号
CertificateSerialNumber csn=new CertificateSerialNumber(sn);
cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);
(8)设置新证书签发者
cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);应用第三步的结果
(9)设置新证书签名算法信息
AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);
(10)创建证书并使用CA的私钥对其签名
X509CertImpl newcert=new X509CertImpl(cinfo2);
newcert.sign(caprk,"MD5WithRSA"); 使用CA私钥对其签名
(11)将新证书写入密钥库
ks.setCertificateEntry("lf_signed",newcert);
FileOutputStream out=new FileOutputStream("newstore");
ks.store(out,"newpass".toCharArray()); 这里是写入了新的密钥库,也可以使用第七条来增加条目
十:数字证书的检验
(1)验证证书的有效期
(a)获取X509Certificate类型对象
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in1=new FileInputStream("aa.crt");
java.security.cert.Certificate c1=cf.generateCertificate(in1);
X509Certificate t=(X509Certificate)c1;
in2.close();
(b)获取日期
Date TimeNow=new Date();
(c)检验有效性
try{
t.checkValidity(TimeNow);
System.out.println("OK");
}catch(CertificateExpiredException e){ //过期
System.out.println("Expired");
System.out.println(e.getMessage());
}catch((CertificateNotYetValidException e){ //尚未生效
System.out.println("Too early");
System.out.println(e.getMessage());}
(2)验证证书签名的有效性
(a)获取CA证书
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("caroot.crt");
java.security.cert.Certificate cac=cf.generateCertificate(in2);
in2.close();
(c)获取CA的公钥
PublicKey pbk=cac.getPublicKey();
(b)获取待检验的证书(上步已经获取了,就是C1)
(c)检验证书
boolean pass=false;
try{
c1.verify(pbk);
pass=true;
}catch(Exception e){
pass=false;
System.out.println(e);
}
一:需要包含的包
| import java.security.*; import java.io.*; import java.util.*; import java.security.*; import java.security.cert.*; import sun.security.x509.* import java.security.cert.Certificate; import java.security.cert.CertificateFactory; |
二:从文件中读取证书
用keytool将.keystore中的证书写入文件中,然后从该文件中读取证书信息
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in=new FileInputStream("out.csr");
Certificate c=cf.generateCertificate(in);
String s=c.toString();
三:从密钥库中直接读取证书
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
java.security.cert.Certificate c=ks.getCertificate(alias);//alias为条目的别名
四:JAVA程序中显示证书指定信息
System.out.println("输出证书信息:\n"+c.toString());
System.out.println("版本号:"+t.getVersion());
System.out.println("序列号:"+t.getSerialNumber().toString(16));
System.out.println("主体名:"+t.getSubjectDN());
System.out.println("签发者:"+t.getIssuerDN());
System.out.println("有效期:"+t.getNotBefore());
System.out.println("签名算法:"+t.getSigAlgName());
byte [] sig=t.getSignature();//签名值
PublicKey pk=t.getPublicKey();
byte [] pkenc=pk.getEncoded();
System.out.println("公钥");
for(int i=0;i<pkenc.length;i++)System.out.print(pkenc[i]+",");
五:JAVA程序列出密钥库所有条目
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
Enumeration e=ks.aliases();
while(e.hasMoreElements())
java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());
六:JAVA程序修改密钥库口令
String oldpass="123456";
String newpass="654321";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,oldpass.toCharArray());
in.close();
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,newpass.toCharArray());
output.close();
七:JAVA程序修改密钥库条目的口令及添加条目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
Certificate [] cchain=ks.getCertificate(alias);获取别名对应条目的证书链
PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());获取别名对应条目的私钥
ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密钥库中添加条目
第一个参数指定所添加条目的别名,假如使用已存在别名将覆盖已存在条目,使用新别名将增加一个新条目,第二个参数为条目的私钥,第三个为设置的新口令,第四个为该私钥的公钥的证书链
FileOutputStream output=new FileOutputStream("another");
ks.store(output,storepass.toCharArray())将keystore对象内容写入新文件
八:JAVA程序检验别名和删除条目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
ks.containsAlias("sage");检验条目是否在密钥库中,存在返回true
ks.deleteEntry("sage");删除别名对应的条目
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,storepass.toCharArray())将keystore对象内容写入文件,条目删除成功
九:JAVA程序签发数字证书
(1)从密钥库中读取CA的证书
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
java.security.cert.Certificate c1=ks.getCertificate("caroot");
(2)从密钥库中读取CA的私钥
PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());
(3)从CA的证书中提取签发者的信息
byte[] encod1=c1.getEncoded(); 提取CA证书的编码
X509CertImpl cimp1=new X509CertImpl(encod1); 用该编码创建X509CertImpl类型对象
X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象
X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 获取X509Name类型的签发者信息
(4)获取待签发的证书
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("user.csr");
java.security.cert.Certificate c2=cf.generateCertificate(in);
(5)从待签发的证书中提取证书信息
byte [] encod2=c2.getEncoded();
X509CertImpl cimp2=new X509CertImpl(encod2); 用该编码创建X509CertImpl类型对象
X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象
(6)设置新证书有效期
Date begindate=new Date(); 获取当前时间
Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期为3000天
CertificateValidity cv=new CertificateValidity(begindate,enddate); 创建对象
cinfo2.set(X509CertInfo.VALIDITY,cv); 设置有效期
(7)设置新证书序列号
int sn=(int)(begindate.getTime()/1000); 以当前时间为序列号
CertificateSerialNumber csn=new CertificateSerialNumber(sn);
cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);
(8)设置新证书签发者
cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);应用第三步的结果
(9)设置新证书签名算法信息
AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);
(10)创建证书并使用CA的私钥对其签名
X509CertImpl newcert=new X509CertImpl(cinfo2);
newcert.sign(caprk,"MD5WithRSA"); 使用CA私钥对其签名
(11)将新证书写入密钥库
ks.setCertificateEntry("lf_signed",newcert);
FileOutputStream out=new FileOutputStream("newstore");
ks.store(out,"newpass".toCharArray()); 这里是写入了新的密钥库,也可以使用第七条来增加条目
十:数字证书的检验
(1)验证证书的有效期
(a)获取X509Certificate类型对象
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in1=new FileInputStream("aa.crt");
java.security.cert.Certificate c1=cf.generateCertificate(in1);
X509Certificate t=(X509Certificate)c1;
in2.close();
(b)获取日期
Date TimeNow=new Date();
(c)检验有效性
try{
t.checkValidity(TimeNow);
System.out.println("OK");
}catch(CertificateExpiredException e){ //过期
System.out.println("Expired");
System.out.println(e.getMessage());
}catch((CertificateNotYetValidException e){ //尚未生效
System.out.println("Too early");
System.out.println(e.getMessage());}
(2)验证证书签名的有效性
(a)获取CA证书
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("caroot.crt");
java.security.cert.Certificate cac=cf.generateCertificate(in2);
in2.close();
(c)获取CA的公钥
PublicKey pbk=cac.getPublicKey();
(b)获取待检验的证书(上步已经获取了,就是C1)
(c)检验证书
boolean pass=false;
try{
c1.verify(pbk);
pass=true;
}catch(Exception e){
pass=false;
System.out.println(e);
}
2009年3月31日星期二
Mac OS X Java虚拟机选项
Mac OS X的Java虚拟机除了具有标准的HotSpot虚拟机的选项之外,还支持很多非标准的选项(-X和-XX),本章列出了这些选项以及一些值得注意的例外事项。
请注意: 除非特别声明,否则在一个选项中指定的bytes(字节)都是作为参数。您也可以分别通过k或者m这两个字母来指定千个字节或者兆个字节(大小写都可以)。例如,下面的几种形式都是表示字节数:4194301,4096k,4096K,4m,和4M。
一般选项
-server
在Mac OS X中没有特别的服务器虚拟机(server VM)。在激活java的时候可以使用 -server 选项,但这并不是启动另外的虚拟机,它还是启动客户虚拟机(client VM),只是这个虚拟机针对服务器的使用环境进行了调优。这些调优包括:
在共享档案的生成过程中使用不同的类列表,这个列表中不包括GUI类(见“Mac OS X的Java共享档案”部分)。
增加Java堆的尺寸。
增加Eden代的内存空间的尺寸。
打开线程的本地Eden垃圾收集器(garbage collection)。
-X
显示一个非标准虚拟机选项的简要描述。
-Xbootclasspath:path
指定一个目录以及JAR和ZIP档案的列表,作为搜索启动类的范围。列表中各项之间的分隔符为冒号(:)。
-Xfuture
对类文件执行严格的格式检查。这个选项强制Java对是否遵守类文件规范做更加严格的检查,而缺省的检查只是基于Java 1.1.x的标准。您应该使用这个选项来对代码进行测试,以便确保这些代码在未来的Java版本中能够工作,这些未来的版本可能强制进行更为严格的类文件格式检查。
-Xprof
把运行程序详细的行为分析数据发送给标准输出。在产品级的代码中不能使用这个选项。
-Xrs
和-XX:+ReduceSignalUsage选项一样。
-XX:+ReduceSignalUsage
正常情况下,Java响应SIGHUP,SIGINT,和SIGTERM信号。如果指定了这个选项,则Java会忽略这些信号,您要根据具体的需要在本地代码中实现这些信号的处理函数,同时还要在System.exit()中实现相关的关闭例程。
-XX:ReservedCodeCacheSize=size in bytes
设置最大的代码缓存的大小,缺省情况下是32(32M)。
-XX:-PrintJavaStackAtFatalState
缺省情况下,当本地代码崩溃时,Java会产生回溯(backtraces)信息。如果您在Java的错误报告中看到了崩溃的信息,则可以把这个选项关闭。
Mac OS X 专用选项
-Xdock:name=applicationName
设定应用程序在Dock和菜单条上显示的名称。如果这个选项没有被设定,则缺省情况下Mac OS X会显示主类的全名。您只需要对那些从命令行或者JAR文件中启动的程序设定这个选项,那些可以双击的应用程序包则从Info.plist文件中读取正确的显示名。
-XX:+UseFileLocking
这个选项用来激活Carbon文件的锁定功能,缺省情况下关闭。如果您的Java应用程序和一些文件相互作用,而这些文件同时又受到一些Carbon应用程序的影响,则您需要使用这个选项,它可以避免应用程序修改那些正在被别的程序访问的文件。
堆的尺寸
-Xmssize in bytes
设定Java堆的初始尺寸,缺省尺寸是2097152 (2MB)。这个值必须是1024个字节(1KB)的倍数,且比它大。(-server选项把缺省尺寸增加到32M。)
-Xmnsize in bytes
为Eden对象设定初始Java堆的大小,缺省值为640K。(-server选项把缺省尺寸增加到2M。)
-Xmxsize in bytes
设定Java堆的最大尺寸,缺省值为64M,(-server选项把缺省尺寸增加到128M。) 最大的堆尺寸达到将近2GB(2048MB)。
请注意:很多垃圾收集器的选项依赖于堆大小的设定。请在微调垃圾收集器使用内存空间的方式之前,确认是否已经正确设定了堆的尺寸。
垃圾收集:内存的使用
-XX:MinHeapFreeRatio=percentage as a whole number
修改垃圾回收之后堆中可用内存的最小百分比,缺省值是40。如果垃圾回收后至少还有40%的堆内存没有被释放,则系统将增加堆的尺寸。
-XX:MaxHeapFreeRatio=percentage as a whole number
改变垃圾回收之后和堆内存缩小之前可用堆内存的最大百分比,缺省值为70。这意味着如果在垃圾回收之后还有大于70%的堆内存,则系统就会减少堆的尺寸。
-XX:NewSize=size in bytes
为已分配内存的对象中的Eden代设置缺省的内存尺寸。它的缺省值是640K。(-server选项把缺省尺寸增加到2M。)
-XX:MaxNewSize=size in bytes
允许您改变初期对象空间的上限,新建对象所需的内存就是从这个空间中分配来的,这个选项的缺省值是640K。(-server选项把缺省尺寸增加到2M。)
-XX:NewRatio=value
改变新旧空间的尺寸比例,这个比例的缺省值是8,意思是新空间的尺寸是旧空间的1/8。
-XX:SurvivorRatio=number
改变Eden对象空间和残存空间的尺寸比例,这个比例的缺省值是10,意思是Eden对象空间的尺寸比残存空间大survivorRatio+2倍。
-XX:TargetSurvivorRatio=percentage
设定您所期望的空间提取后被使用的残存空间的百分比,缺省值是50。
-XX:MaxPermSize=size in MB
长久代(permanent generation)的尺寸,缺省值为32(32MB)。
垃圾收集: 一般设定
-Xincgc
Mac OS X不支持这个选项,不支持这种训练式的垃圾收集器。
-Xnoclassgc
禁用类的垃圾收集。
-XX:+UseConcMarkSweepGC
激活标志和清除同时进行的垃圾收集活动,这个选项对多处理器的计算机有效。
-XX:+UseParallelGC
激活并行的垃圾收集活动,这个选项只对多处理器的计算机有效。
-XX:-DisableExplicitGC
忽略代码中对System.gc()的显式调用。虚拟机仍然按照正常的机制进行垃圾收集。这个选项禁止在代码中强制执行垃圾收集。
-XX:+PrintTenuringDistribution
打印初期代中已分配内存的对象占用内存时间的信息。
编译
-Xint
只在解释(interperated)模式下运行虚拟机。如果使用这个选项,系统将不编译任何字节码。
-XX:CompileThreshold=value
在编译开始前改变方法调用(程序分支)的数目,缺省值是1000。
-XX:-InlineUnreachableCalls
缺省情况下,虚拟机对所有可能的代码进行方法内联处理(method inlining),以方便编译器进行优化。对这个选项进行设定会使较少的代码按照内联方法被编译。这样,那些正常情况下不会运行的代码,如例外处理,就不会被处理为内联代码,而只能在运行时进行解释。设定这个选项可能会大大降低性能。
-XX:+CITime
显示有多少时间花在编译过的代码上。
-XX:+PrintCompilation
在Java的方法被编译时,打印其的跟踪信息。
Threading
-XX:NewSizeThreadIncrease=size in KB
允许您指定每个活动线程会增加多少初期对象空间。这个选项在调节由于线程增加而增加的分配率时可能会有用。它的缺省值为16(16 kilobytes)。
-XX:ThreadStackSize=size in KB
改变线程栈的大小。缺省情况下,线程栈的大小就是操作系统所使用的栈的缺省大小。
-XX:+UseTLAB
激活线程本地的分配缓冲区。 使用这个缓冲区将使线程任务繁重的应用程序的内存分配更加具有可扩展性,大大提高内存分配的性能。这个选项在多处理器的计算机和Mac OS X Server上缺省打开。
共享
-XX:+PrintSharedSpace
打开共享的冗长输出。
-XX:-UseSharedSpaces
关闭共享。
请注意: 除非特别声明,否则在一个选项中指定的bytes(字节)都是作为参数。您也可以分别通过k或者m这两个字母来指定千个字节或者兆个字节(大小写都可以)。例如,下面的几种形式都是表示字节数:4194301,4096k,4096K,4m,和4M。
一般选项
-server
在Mac OS X中没有特别的服务器虚拟机(server VM)。在激活java的时候可以使用 -server 选项,但这并不是启动另外的虚拟机,它还是启动客户虚拟机(client VM),只是这个虚拟机针对服务器的使用环境进行了调优。这些调优包括:
在共享档案的生成过程中使用不同的类列表,这个列表中不包括GUI类(见“Mac OS X的Java共享档案”部分)。
增加Java堆的尺寸。
增加Eden代的内存空间的尺寸。
打开线程的本地Eden垃圾收集器(garbage collection)。
-X
显示一个非标准虚拟机选项的简要描述。
-Xbootclasspath:path
指定一个目录以及JAR和ZIP档案的列表,作为搜索启动类的范围。列表中各项之间的分隔符为冒号(:)。
-Xfuture
对类文件执行严格的格式检查。这个选项强制Java对是否遵守类文件规范做更加严格的检查,而缺省的检查只是基于Java 1.1.x的标准。您应该使用这个选项来对代码进行测试,以便确保这些代码在未来的Java版本中能够工作,这些未来的版本可能强制进行更为严格的类文件格式检查。
-Xprof
把运行程序详细的行为分析数据发送给标准输出。在产品级的代码中不能使用这个选项。
-Xrs
和-XX:+ReduceSignalUsage选项一样。
-XX:+ReduceSignalUsage
正常情况下,Java响应SIGHUP,SIGINT,和SIGTERM信号。如果指定了这个选项,则Java会忽略这些信号,您要根据具体的需要在本地代码中实现这些信号的处理函数,同时还要在System.exit()中实现相关的关闭例程。
-XX:ReservedCodeCacheSize=size in bytes
设置最大的代码缓存的大小,缺省情况下是32(32M)。
-XX:-PrintJavaStackAtFatalState
缺省情况下,当本地代码崩溃时,Java会产生回溯(backtraces)信息。如果您在Java的错误报告中看到了崩溃的信息,则可以把这个选项关闭。
Mac OS X 专用选项
-Xdock:name=applicationName
设定应用程序在Dock和菜单条上显示的名称。如果这个选项没有被设定,则缺省情况下Mac OS X会显示主类的全名。您只需要对那些从命令行或者JAR文件中启动的程序设定这个选项,那些可以双击的应用程序包则从Info.plist文件中读取正确的显示名。
-XX:+UseFileLocking
这个选项用来激活Carbon文件的锁定功能,缺省情况下关闭。如果您的Java应用程序和一些文件相互作用,而这些文件同时又受到一些Carbon应用程序的影响,则您需要使用这个选项,它可以避免应用程序修改那些正在被别的程序访问的文件。
堆的尺寸
-Xmssize in bytes
设定Java堆的初始尺寸,缺省尺寸是2097152 (2MB)。这个值必须是1024个字节(1KB)的倍数,且比它大。(-server选项把缺省尺寸增加到32M。)
-Xmnsize in bytes
为Eden对象设定初始Java堆的大小,缺省值为640K。(-server选项把缺省尺寸增加到2M。)
-Xmxsize in bytes
设定Java堆的最大尺寸,缺省值为64M,(-server选项把缺省尺寸增加到128M。) 最大的堆尺寸达到将近2GB(2048MB)。
请注意:很多垃圾收集器的选项依赖于堆大小的设定。请在微调垃圾收集器使用内存空间的方式之前,确认是否已经正确设定了堆的尺寸。
垃圾收集:内存的使用
-XX:MinHeapFreeRatio=percentage as a whole number
修改垃圾回收之后堆中可用内存的最小百分比,缺省值是40。如果垃圾回收后至少还有40%的堆内存没有被释放,则系统将增加堆的尺寸。
-XX:MaxHeapFreeRatio=percentage as a whole number
改变垃圾回收之后和堆内存缩小之前可用堆内存的最大百分比,缺省值为70。这意味着如果在垃圾回收之后还有大于70%的堆内存,则系统就会减少堆的尺寸。
-XX:NewSize=size in bytes
为已分配内存的对象中的Eden代设置缺省的内存尺寸。它的缺省值是640K。(-server选项把缺省尺寸增加到2M。)
-XX:MaxNewSize=size in bytes
允许您改变初期对象空间的上限,新建对象所需的内存就是从这个空间中分配来的,这个选项的缺省值是640K。(-server选项把缺省尺寸增加到2M。)
-XX:NewRatio=value
改变新旧空间的尺寸比例,这个比例的缺省值是8,意思是新空间的尺寸是旧空间的1/8。
-XX:SurvivorRatio=number
改变Eden对象空间和残存空间的尺寸比例,这个比例的缺省值是10,意思是Eden对象空间的尺寸比残存空间大survivorRatio+2倍。
-XX:TargetSurvivorRatio=percentage
设定您所期望的空间提取后被使用的残存空间的百分比,缺省值是50。
-XX:MaxPermSize=size in MB
长久代(permanent generation)的尺寸,缺省值为32(32MB)。
垃圾收集: 一般设定
-Xincgc
Mac OS X不支持这个选项,不支持这种训练式的垃圾收集器。
-Xnoclassgc
禁用类的垃圾收集。
-XX:+UseConcMarkSweepGC
激活标志和清除同时进行的垃圾收集活动,这个选项对多处理器的计算机有效。
-XX:+UseParallelGC
激活并行的垃圾收集活动,这个选项只对多处理器的计算机有效。
-XX:-DisableExplicitGC
忽略代码中对System.gc()的显式调用。虚拟机仍然按照正常的机制进行垃圾收集。这个选项禁止在代码中强制执行垃圾收集。
-XX:+PrintTenuringDistribution
打印初期代中已分配内存的对象占用内存时间的信息。
编译
-Xint
只在解释(interperated)模式下运行虚拟机。如果使用这个选项,系统将不编译任何字节码。
-XX:CompileThreshold=value
在编译开始前改变方法调用(程序分支)的数目,缺省值是1000。
-XX:-InlineUnreachableCalls
缺省情况下,虚拟机对所有可能的代码进行方法内联处理(method inlining),以方便编译器进行优化。对这个选项进行设定会使较少的代码按照内联方法被编译。这样,那些正常情况下不会运行的代码,如例外处理,就不会被处理为内联代码,而只能在运行时进行解释。设定这个选项可能会大大降低性能。
-XX:+CITime
显示有多少时间花在编译过的代码上。
-XX:+PrintCompilation
在Java的方法被编译时,打印其的跟踪信息。
Threading
-XX:NewSizeThreadIncrease=size in KB
允许您指定每个活动线程会增加多少初期对象空间。这个选项在调节由于线程增加而增加的分配率时可能会有用。它的缺省值为16(16 kilobytes)。
-XX:ThreadStackSize=size in KB
改变线程栈的大小。缺省情况下,线程栈的大小就是操作系统所使用的栈的缺省大小。
-XX:+UseTLAB
激活线程本地的分配缓冲区。 使用这个缓冲区将使线程任务繁重的应用程序的内存分配更加具有可扩展性,大大提高内存分配的性能。这个选项在多处理器的计算机和Mac OS X Server上缺省打开。
共享
-XX:+PrintSharedSpace
打开共享的冗长输出。
-XX:-UseSharedSpaces
关闭共享。
订阅:
博文 (Atom)