日志分类:Java技术

5月Tiobe编程语言榜单出炉 苹果势力彰显

2010年05月19日 7:36 上午  |  分类:Java技术

       Tiobe周末发布了5月份编程语言排行榜,和上月相同,C语言仍然占据着第一的宝座,而四年来一直独占鳌头的Java本月也还是屈居第二。 C++、PHP、Visual Basic、C#、Python、Perl、Delphi的排名与上月相同,分居第3至9位。

  值得一提的是,尽管增幅仅为0.08%,但是Object-C首次进入排行版前十榜单,“这很了不起,因为自从2001年6月开始TIOBE排名以来,仅有13个主流编程语言进入前十。”Object-C流行的一个主要原因是,它是唯一一个可以为iPhone或iPad编写应用程序的语言。从编程语言的角度来看,Object-C(诞生于1986年)并没有提供什么新的功能。

JAVA中的main函数详细讲解

2010年05月19日 7:35 上午  |  分类:Java技术

       JAVA中的主函数是我们再熟悉不过的了,相信每个学习过JAVA语言的人都能够熟练地写出这个程序的入口函数,但对于主函数为什么这么写,其中的每个关键字分别是什么意思,可能就不是所有人都能轻松地答出来的了。我也是在学习中碰到了这个问题,通过在网上搜索资料,并加上自己的实践终于有了一点心得,不敢保留,写出来与大家分享。

  主函数的一般写法如下:

  public static void main(String[] args){…}

  下面分别解释这些关键字的作用:

  (1)public关键字,这个好理解,声明主函数为public就是告诉其他的类可以访问这个函数。

  (2)static关键字,告知编译器main函数是一个静态函数。也就是说main函数中的代码是存储在静态存储区的,即当定义了类以后这段代码就已经存在了。如果main()方法没有使用static修饰符,那么编译不会出错,但是如果你试图执行该程序将会报错,提示main()方法不存在。因为包含main()的类并没有实例化(即没有这个类的对象),所以其main()方法也不会存。而使用 static修饰符则表示该方法是静态的,不需要实例化即可使用。

  (3)void关键字表明main()的返回值是无类型。

  **(4)参数String[] args,这是本文的重点。

  第一、程序使用者可以在命令行状态下向某个类传递参数。看下面的例子:

  public class ArgsDemo {

  public static void main(String[] args) {

  String str = new String();

  for (int i = 0; i < i++)>

  System.out.println(args[i]);

  str += args[i];

  }

  System.out.println(str);

  }

  }

  使用javac ArgsDemo.java命令生成ArgsDemo.class文件;然后使用“java ArgsDemo 参数一 参数二 参数三 …”的格式向ArgsDemo类传递参数。该示例程序将首先输出参数,然后输出所有参数的和。比如java ArgsDemo a b c,将得到这样的输出:

  a

  b

  c

  abc

  需要注意的是,如果这里的循环条件不是i <5,则在命令行中输入的参数必须是5个,否则将会报错,错误类型为:<>

  Exception in thread “main” java.lang.ArrayIndexOutOfBoundException:3

  at ArgsDemo.main(ArgsDemo.java:5)

  第二、可以在另一个类中向包含main()的类传递参数,如下例:

  public class A {

  public static void main(String[] args)

  {

  for(int i=0;i < p>

  System.out.println(args[i]);

  }

  }

  public class B {

  public static void main(String[] args)

  {

  c = new A();

  String[] b = {”111″,”222″,”333″};

  c.main(b);

  }

  }

  首先定义一个class A,在A中定义一个main()函数,在该函数中输出参数args。然后定义一个classB,在B中初始化一个A的实例c,然后向c传递参数,并且调用 c的main方法打印出传入的参数值。输出结果如下:

  111

  222

  333

  由于main()函数是静态函数,即不需要实例化也能使用,所以B使用下面的写法也能完成相同的功能:

  public class B {

  public static void main(String[] args)

  {

  //A c = new A();

  String[] b = {”111″,”222″,”333″};

  A.main(b);

  }

  }

  总结:参数args的主要作用是为程序使用者在命令行状态下与程序交互提供了一种手段。此外在其他类中直接使用main()函数,并传递参数也是可行的,虽然这种方法不太常用,但毕竟为我们提供了一种选择。

 

Java对数函数及Java对数运算

2010年05月16日 10:15 上午  |  分类:Java技术
  Java对数函数的计算方法非常有问题,然而在API中却有惊人的误差。但是假如运用了以下的方法,用Java处理数字所碰到的小麻烦就可以轻而易举的解决了。

  Sun的J2SE提供了一个单一的Java对数方法——double java.lang.Math.log(double),这很轻易使用。请看如下代码:

  double x = Math.log(5);

  等价于:x = ln 5 或 x = loge5,即以e为底的自然对数。

  假如你想使用Java来计算机对数,算底不同的对数又该如何做呢?很遗憾,我们还没有办法计算以10为底或以2为底的对数。但是它们却是在计算Java对数时用的最多的。要想解决这个问题,需要使用数学和对数方程:

  logx(y) =loge(x) / loge(y),换底公式

  这只需一段简单的Java程序来实现对数的运算:

  package com.generationjava.math;

  public class Logarithm {

  static public double log(double value, double base) {

  return Math.log(value) / Math.log(base);

  }

  }

  使用Java对数函数计算100的以10为底的对数就变为非常简单了:

  double log = Logarithm.log(100, 10); // log is 2.0

  512的以2为底的对数是:

  double log = Logarithm.log(512, 2); // log is 9.0

  下面的两个简单的Java对数运算方法也都是很有用的:

  static  public double log2(double value) {

  return log(value, 2.0);

  }

  static public double log10(double value) {

  return log(value, 10.0);

  }

Java语言中的ClassLoader与Package机制

2010年05月16日 10:13 上午  |  分类:Java技术

     为了深入了解Java的ClassLoader机制,我们先来做以下实验:

  package java.lang;public class Test { public static void main(String[] args) { char[] c = “1234567890″.toCharArray(); String s = new String(0, 10, c);}}

  String类有一个Package权限的构造函数String(int offset, int length, char[] array),按照默认的访问权限,由于Test属于java.lang包,因此理论上应该可以访问String的这个构造函数。编译通过!执行时结果如下:

  Exception in thread “main” java.lang.SecurityException:Prohibited package name:java.lang at java.lang.ClassLoader.defineClass(Unknown Source) at java.security.SecureClassLoader.defineClass(Unknown Source) at java.net.URLClassLoader.defineClass(Unknown Source) at java.net.URLClassLoader.access$100(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClassInternal(Unknown Source)

  希奇吧?要弄清为什么会有SecurityException,就必须搞清楚ClassLoader的机制。

  Java的ClassLoader就是用来动态装载class的,ClassLoader对一个class只会装载一次,JVM使用的ClassLoader一共有4种:

  启动类装载器,标准扩展类装载器,类路径装载器和网络类装载器。

  这4种ClassLoader的优先级依次从高到低,使用所谓的“双亲委派模型”。确切地说,假如一个网络类装载器被请求装载一个java.lang.Integer,它会首先把请求发送给上一级的类路径装载器,假如返回已装载,则网络类装载器将不会装载这个java.lang.Integer,假如上一级的类路径装载器返回未装载,它才会装载java.lang.Integer.

  类似的,类路径装载器收到请求后(无论是直接请求装载还是下一级的ClassLoader上传的请求),它也会先把请求发送到上一级的标准扩展类装载器,这样一层一层上传,于是启动类装载器优先级最高,假如它按照自己的方式找到了java.lang.Integer,则下面的ClassLoader 都不能再装载java.lang.Integer,尽管你自己写了一个java.lang.Integer,试图取代核心库的java.lang.Integer是不可能的,因为自己写的这个类根本无法被下层的ClassLoader装载。

  再说说Package权限。Java语言规定,在同一个包中的class,假如没有修饰符,默认为Package权限,包内的class都可以访问。但是这还不够准确。确切的说,只有由同一个ClassLoader装载的class才具有以上的Package权限。比如启动类装载器装载了java.lang.String,类路径装载器装载了我们自己写的java.lang.Test,它们不能互相访问对方具有Package权限的方法。这样就阻止了恶意代码访问核心类的Package权限方法。

  为了深入了解Java的ClassLoader机制,我们先来做以下实验:

  package java.lang;public class Test { public static void main(String[] args) { char[] c = “1234567890″.toCharArray(); String s = new String(0, 10, c);}}

  String类有一个Package权限的构造函数String(int offset, int length, char[] array),按照默认的访问权限,由于Test属于java.lang包,因此理论上应该可以访问String的这个构造函数。编译通过!执行时结果如下:

  package java.lang;

  public class Test {

  public static void main(String[] args) {

  char[] c = “1234567890″.toCharArray();

  String s = new String(0, 10, c);

  }

  }

  Exception in thread “main” java.lang.SecurityException:

  Prohibited package name:

  java.lang

  at java.lang.ClassLoader.defineClass(Unknown Source)

  at java.security.SecureClassLoader.defineClass(Unknown Source)

  at java.net.URLClassLoader.defineClass(Unknown Source)

  at java.net.URLClassLoader.access$100(Unknown Source)

  at java.net.URLClassLoader$1.run(Unknown Source)

  at java.security.AccessController.doPrivileged(Native Method)

  at java.net.URLClassLoader.findClass(Unknown Source)

  at java.lang.ClassLoader.loadClass(Unknown Source)

  at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)

  at java.lang.ClassLoader.loadClass(Unknown Source)

  at java.lang.ClassLoader.loadClassInternal(Unknown Source)

OSGi依赖性管理:Bundle访问域

2010年05月14日 7:45 上午  |  分类:Java技术

     OSGi依赖性管理

  OSGi允许您把您的应用程序分成多个模块,并能管理这些模块之间的依赖性。为了达到这个目的,它引入了Bundle访问域的概念。Bundle中类的缺省访问范围只对本Bundle内部可见,但对其它任何Bundle都是不可见的;在Bundle内部,类的可访问性遵循Java语言的一般规范。那么,您如果想要从一个Bundle中访问另一个Bundle中的类,您应该怎么办呢?解决方法是将源Bundle中的包导出来,然后把它们导入到目标Bundle中。在本小结中,我们将通过一个示例程序说明这个概念。

  首先,我们新建一个名com.javaworld.sample.HelloService的Bundle,并从其中导出一个包,然后将该包导入到我们的com.javaworld.sample.HelloWorld Bundle中。

  1. 导出Java

  我们开始新建一个com.javaworld.sample.HelloServiceBundle,并从其中导出一个Java包,具体步骤如下:

  1) 新建com.javaworld.sample.HelloService Bundle,具体步骤请参见上小节中新建com.javaworld.sample.HelloWorldBundle的步骤;

  2) 在HelloService Bundle中,新建一个com.javaworld.sample.service.HelloService.java接口,其源代码如清单3所示。

  源代码清单3. HelloService.java

  1.package com.javaworld.sample.service;

  2.public interface HelloService {

  3.public String sayHello();

  }

  5.

  3) 新建类com.javaworld.sample.service.impl.HelloServiceImpl.java,该类实现HelloService接口,其源代码如清单4所示。

  源代码清单4. HelloServiceImpl.java

  6.package com.javaworld.sample.service.impl;

  7.import com.javaworld.sample.service.HelloService;

  8.public class HelloServiceImpl implements HelloService {

  9.public StringsayHello() {

  10.System.out.println(”InsideHelloServiceImple.sayHello()”);

  11.return”Say Hello”;

  12.}

  13.}

  14.

  4) 请在您的Eclipse Manifest编辑器中打开HelloService包中的MANIFEST.MF文件,点击“Runtime(运行时)” 标签,在“导出包”小节,单击“Add(添加)”按钮,并选择com.javaworld.sample.service包。这时,HelloServiceBundle中的MANIFEST.MF文件代码应如源代码清单5所示。

  源代码清单5. HelloService Bundle中的Manifest文件

  15.Manifest-Version: 1.0

  16.Bundle-ManifestVersion: 2

  17.Bundle-Name: HelloService Plug-in

  18.Bundle-SymbolicName:com.javaworld.sample.HelloService

  19.Bundle-Version: 1.0.0

  20.Bundle-Vendor: JAVAWORLD

  21.Bundle-Localization: plugin

  22.Export-Package: com.javaworld.sample.service

  23.Import-Package:org.osgi.framework;version=”1.3.0″

  24.

  您可以看到,HelloService Bundle中的MANIFEST.MF文件和HelloWorldBundle非常相似,唯一的区别就是多了一个Export-Package属性头,该属性头的值为com.javaworld.sample.service;Export-Package属性头通知OSGi容器,其它Bundle可以从HelloService Bundle外面访问com.javaworld.sample.service包中的类。请注意,在示例代码中,我们只暴露了接口类HelloService,而没有暴露其实现类的HelloServiceImpl。

  2. 导入Java包

  下面,我们将从HelloServiceBundle中导出的com.javaworld.sample.service包并将其导入到HelloWorldBundle中,具体步骤如下:

  1). 请在com.javaworld.sample.HelloWorld Bundle中找到MANIFEST.MF文件,并在Manifest编辑器中打开,点击“Dependencies(依赖性)”标签,然后点击“ImportPackage(导入包)”按钮,将com.javaworld.sample.service添加为导入包,这时,您的HelloWorldBundle中的MANIFEST.MF文件内容应如源代码清单6所示:

  源代码清单6. HelloWorld Bundle中的MANIFEST.MF文件

  25.Manifest-Version: 1.0

  26.Bundle-ManifestVersion: 2

  27.Bundle-Name: HelloWorld Plug-in

  28.Bundle-SymbolicName: com.javaworld.sample.HelloWorld

  29.Bundle-Version: 1.0.0

  30.Bundle-Activator: com.javaworld.sample.helloworld.Activator

  31.Bundle-Vendor: JAVAWORLD

  32.Bundle-Localization: plugin

  33.Import-Package: com.javaworld.sample.service,

  34.org.osgi.framework;version=”1.3.0″

  35.

  从上面的代码可以看出,Import-Package属性头的值是一个由逗号分隔的字符串,这是您想导入包的列表。在HelloWorldBundle示例代码中,我们引入了两个包,即com.javaworld.sample.service和org.osgi.framework。

  org.osgi.framework包中包含有OSGi框架类,比如,在HelloWorldBundle中的Activator.java中用到的BundleContext和BundleActivator类都属于这个包。

  2) 下面,请在Eclipse Java编辑器中打开com.javaworld.sample.helloworld.Activator.java,您会注意到,您现在可以访问HelloService接口,但不能访问HelloServiceImpl实现类,这是因为HelloServiceBunlde只导出了com.javaworld.sampel.service包,同时HelloWorldBundle也导入了这个包。HelloServiceImpl是HelloServiceBundle的一个内部类,任何其它的Bundle都不能访问它。

  3. 类级别上的访问域

  如果您运行示例的HelloService服务包,它会在Eclipse控制台上打印出”HelloWorld”。但是,如果您想在HelloWorld Bundle的Activator中访问HelloServiceImpl类,这时,编译没有问题,但在OSGi容器中运行这个Bundle时会抛出异常。

  OSGi容器是如何能将jar文件中的一些类隐藏掉,而让另外一些类可见呢?这是因为OSGi容器使用Java类加载器来管理类的可见性,OSGi容器为每个Bundle创建不同的类加载器,因此每个Bundle能访问位于下列位置中的类:

  a) 位于Java启动类路径下的、所有以Java.*开头的包中的类;

  b) 位于OSGi框架类路径下的类,通常有一个独立的类加载器负责加载框架的实现类及关键的接口类;

  c) 位于Bundle空间中的类,这些类通常包含在与Bundle相关的jar文件中,以及加到这个Bundle中的其它jar包中的类。

  d) 导入包中的类,例如,HelloWorld Bundle导入了com.javaworld.sample.service包,因此它能访问该包中的类。Bundle级别的访问域是OSGi一个非常强大的功能,例如,它可以让您安全地更新HelloServiceImpl.java类,而不必担心依赖于这个类的代码受到破坏。

  以上就大概介绍了OSGi依赖性管理的概念。

三步完成Windows Azure平台部署WCF服务

2010年05月12日 8:57 上午  |  分类:Java技术

       之前,我们在Windows Azure平台简介中介绍过Windows Azure的三大主要功能。那就是计算,存储,以及管理。至今为止,通过之前的教学文章,大家已经熟知了Windows Azure的存储功能。当然,存储只是最基本的一个功能。要充分发挥云计算的威力,我们不得不学习如何“计算”。

  同样在Windows Azure平台简介中,我们也介绍了Windows Azure的三种主要计算功能:

  作为一个部署服务平台

  作为一个软件分发平台

  作为一个一般的分布式计算平台

  本文将引导大家达成第一种功能:在Windows Azure上部署服务。后续文章将会介绍另两种功能。事实上,在Windows Azure入门教学系列 (一): 创建第一个WebRole程序里,大家已经尝试过部署一个最简单的服务:一个ASP.NET网站。是的,ASP.NET网站也可以称作一种服务。现在,你的ASP.NET程序不再是运行在你自己的服务器上,而是运行在云端了。但是,Windows Azure不仅仅支持常规网站,我们也完全可以把那些和用户界面无关的服务(headless services)部署至云端。例如,WCF服务,WF工作流,等等。而也正是这些headless services,使我们的web site摇身一变成为了Web API,让用户可以使用任意大小的屏幕,在任意场合,使用他们喜欢的客户端,访问我们的服务。本文将会教导大家如何在Windows Azure上部署一个WCF服务,作为入门教学,我们将使用最简单的SOAP Service。

  如果你并不了解WCF,请开始学习。本文假设你已经了解了WCF的基础知识。

  前期准备

  想要在Windows Azure这样的负载平衡环境中使用WCF,首先必须下载一个hotfix。这个hotfix已经预装在云端的服务器上,但是如果你要在本地测试,还需要手工装到本机。这个hotfix解决了WCF的一些在负载平衡场合下可能出现的bug。

  创建并观察项目

  创建一个新的Cloud Service项目。选择添加一个WCF Service Web Role。

  在这个入门教学中,我们将使用最基本的,默认生成的代码。以下是默认生成的OperationContracts:

  [OperationContract]

  string GetData(int value);

  [OperationContract]

  CompositeType GetDataUsingDataContract(CompositeType composite);

  打开web.config,请注意默认生成的配置使用的便是basicHttpBinding。可是如果使用普通的WCF Service项目模板,你将会得到wsHttpBinding。注意wsHttpBinding默认使用Windows Authentication,在Windows Azure中Windows Authentication是不支持的,所以如果你使用普通的WCF Service项目模板,请记得修改wsHttpBinding的安全配置,或者改成使用basicHttpBinding。

  负载平衡带来的问题

  现在,运行项目,你会看到标准的WCF信息页面

  请注意WSDL文件的地址并不正确,我们的服务应该是运行在81端口上,但是该页面确报告WSDL文件位于端口5100。假设你点击上述链接,将会得到一个400 Bad Request错误。即使你强制在浏览器中输入http://127.0.0.1:81/Service1.svc?wsdl,你会发现虽然的确可以看到WSDL文件,但是生成的WSDL文件并不正确,包含一系列诸如 这样的链接。如果你尝试在一个客户端程序中add service reference,就会遇上错误了。

  以上,正是WCF默认的行为在负载平衡场合下会引发的问题。事实上,我们的服务的第一个实例(至少在本地模拟环境中)确实运行在端口5100上,如果你的Web Role有多个实例,第二个实例很可能会运行在端口5101上。但是负载平衡器对外暴露的端口永远是你在csdef文件中指定的端口(当然在本地因为80端口已经被IIS占用,不得不使用81端口)。WCF默认并不知道负载平衡器,所以它还是认为客户端必须访问端口5100。

  解决负载平衡带来的问题

  之前我们提到过WCF团队已经研发了一个hotfix,用于解决负载平衡带来的问题。但是为了发挥该hotfix的功效,必须做一点配置。

  首先,在web.config中找到服务的service behavior,并且添加一个名为useRequestHeadersForMetadataAddress的behavior。这个行为是通过hotfix安装的。

<behavior name=WCFServiceWebRole1.Service1Behavior>          <serviceMetadata httpGetEnabled=true/>

                              

          <! To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information –>

          <serviceDebug includeExceptionDetailInFaults=false/>

                                 <! 启用hotfix解决负载平衡造成的端口不正确问题。 –>

                                  <useRequestHeadersForMetadataAddress>

                                        <defaultPorts>

                                               <add scheme=http port=80 />

                                               <add scheme=https port=443 />

                                        </defaultPorts>

                                 </useRequestHeadersForMetadataAddress>

                           </behavior>

 

  

          <! To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>

  再有,在负载平衡场合,客户端所请求的地址往往和服务所部署的真正地址是不同的。因此我们推荐大家将AddressFilterMode设置成Any,从而不再检查地址匹配性。

  [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

  public class Service1 : IService1

  现在,再次运行程序,你会看到端口81已经被成功识别出来。

  将Web Role部署至云端

  将Web Role部署至云端,这个过程是完全一致的,不管你使用ASP.NET,使用WCF,或者使用其它技术。本文不再重复。

  现在,你可以尝试在本地构建一个客户端程序访问刚发布的服务,不过本文就不再详细介绍如何访问服务了。再下一篇文章中,我们将会从云端分发一个软件,并且让那个软件和我们的服务交互,协同工作。

  总结

  你可以在Windows Azure上部署任意服务,而为了充分发挥云计算的威力,我们往往不仅仅需要使用诸如ASP.NET之类的技术制作的web site,更需要使用诸如WCF之类的技术制作的Web API,从而真正地通过云,将所有种类的客户端连接起来。

  在Windows Azure中使用WCF和在一般场合下使用WCF非常类似,但是我们必须注意负载平衡可能带来的问题,并做好应对方案。

C++与java求异存同 java面向对象更出色

2010年05月11日 8:06 上午  |  分类:Java技术

        Java的前身Oak是在C++的基础上开发的,而C++是在C的基础上开发的。因此,Java和C、C++具有许多相似之处,它继承了C、C++的优点,增加了一些实用的功能,并让Java 语言更加精炼;摒弃了C、C++的缺点,去掉了C、C++的指针运算、结构体定义、手工释放内存等容易引起错误的功能和特征,增强了Java的安全性,也让Java更容易被接受和学习。

  虽然Java是在C++的基础上开发的,但并不是C++的增强版,也不是用来取代C++的。Java与C++既不向上兼容,也不向下兼容,两者将长时间共存。Java在理论和实践上都与C++有着重要的不同点。Java是独立于平台的、面向Internet的分布式编程语言,Java对Internet编程的影响如同C和C++对系统编程的影响。Java的出现改变了编程方式,但Java并不是孤立存在的一种语言,而是计算机语言多年来演变的结果。

Java开源项目Hibernate快速入门

2010年05月6日 10:13 上午  |  分类:Java技术, 默认

         final类:为防止他人从你的类上派生新类,此类是不可扩展的。

        动态调用比静态调用花费的时间要长。

        抽象类:规定一个或多个抽象方法的类本身必须定义为abstract。

        例: public abstract string getDescripition

        Java中的每一个类都是从Object类扩展而来的。

        object类中的equal和toString方法。

        equal用于测试一个对象是否同另一个对象相等。

        toString返回一个代表该对象的字符串,几乎每一个类都会重载该方法,以便返回当前状态的正确表示。(toString 方法是一个很重要的方法)

        通用编程:任何类类型的所有值都可以同object类型的变量来代替。

        数组列表:ArrayList动态数组列表,是一个类库,定义在java.uitl包中,可自动调节数组的大小。

        class类 object类中的getclass方法返回class类型的一个实例,程序启动时包含在main方法的类会被加载,虚拟机要加载他需要的所有类,每一个加载的类都要加载它需要的类。

        就业方向:

        可以从事JSP网站开发、Java编程、Java游戏开发、Java桌面程序设计,以及其他与Java语言编程相关的工作。可进入电信、银行、保险专业软件开发公司等从事软件设计和开发工作。

        Java与C/C++的差异

        熟悉C语言和C++语言的读者一定想搞清楚这个问题,实际上,Java确实是从C语言和C++语言继承了许多成份,甚至可以将Java看成是类C语言发展和衍生的产物.比如Java语言的变量声明,操作符形式,参数传递,流程控制等方面和C语言,C++语言完全相同.尽管如此,Java和C语言,C++语言又有许多差别,主要表现在如下几个方面:

        (1) Java中对内存的分配是动态的,它采用面向对象的机制,采用运算符new为每个对象分配内存空间,而且,实际内存还会随程序运行情况而改变.程序运行中,每个, Java系统自动对内存进行扫描,对长期不用的空间作为”垃圾”进行收集,使得系统资源得到更充分地利用.按照这种机制,程序员不必关注内存管理问题,这使Java程序的编写变得简单明了,并且避免了了由于内存管理方面的差错而导致系统出问题.而C语言通过malloc()和free()这两个库函数来分别实现分配内在和释放内存空间的,C++语言中则通过运算符new和delete来分配和释放内存.在C和C++这仲机制中,程序员必须非常仔细地处理内存的使用问题.一方面,如果对己释放的内存再作释放或者对未曾分配的内存作释放,都会造成死机;而另一方面,如果对长期不用的或不再使用的内存不释放,则会浪费系统资源,甚至因此造成资源枯竭.

企业SOA安全:没有最好 只有更好

2010年05月6日 10:07 上午  |  分类:Java技术

安全不是对面向服务架构(SOA)避而远之的理由。虽然SOA安全还没有完全成熟起来,但如今有30%的企业在使用SOA与外部的客户和合作伙伴进行集成。对使用简单对象访问协议(SOAP)的标准Web服务而言,WS-Security规范达到了作为一项基本标准所需的临界规模。另一方面,高级的SOA安全解决方案――涉及合作伙伴之间的联合、不可否认性(nonrepudiation)以及跨实现的多层服务传播用户身份――还处于初期阶段。为了从如今的实用阶段进入到将来的高级SOA安全阶段,你就要为完善SOA安全架构建立一个反复迭代设计过程;这个架构要考虑目前及将来的安全要求、新兴的行业规范、SOA安全方面产品功能的重叠,以及可能需要定制的安全集成。

  作为设计SOA安全的基础,为SOA请求和响应确保安全的最简单方法就是,把它们放在虚拟专用网(VPN)里面。确保外部SOA安全的最常用方法就是使用双向安全套接层(SSL)协议,该协议:

  1)允许彼此联系的各合作伙伴都能验证对方的身份;

  2)为安全设定了高标准。

  除非黑客从服务使用者处窃取了证书和密钥,否则他们甚至无法连接到基于SOA的服务。虽然建立VPN比较容易,但基于VPN的SOA安全存在粗粒度(coarse-grained)的弊端,也没有能力来支持一些高级功能,比如跨实现的多层服务传播用户身份;多个安全域之间的协调和联合;以及严格的不可否认性。另外,证书日常管理可能会成为管理负担。

  确保SOA安全的其他重要办法包括:利用Java或.NET应用平台中现有的SOA安全特性,或把SOA专业产品中的SOA安全特性结合起来,比如企业服务总线、SOA和Web服务管理解决方案、SOA安全服务或SOA硬件设备等产品。硬件设备为SOA安全提供了最简单、最专门的“嵌入式”(drop-in)解决方案;不过构建整体SOA平台时,需要考虑SOA专业产品具有的一些优缺点                                                                        SOA架构的层次

  借助应用服务器和SOA专业产品的新兴功能,连一些简单的SOA安全解决方案也很诱人。在过去,企业一直不太情愿处理实现高级应用安全要求所面临的困难。随着实现的SOA安全机制不断成熟――加上有了更广泛的架构来实现安全联合,实现高级安全场景就会比较容易。许多用户企业会发现,高级SOA安全成了一项必需的要求――特别是由于数据隐私及其他法规越来越多,更是如此。因而有必要事先料到在业务要求需要、SOA安全成熟度允许的情况下,需要构建更深入的额外安全功能,并为之留出余地,哪怕你从简单的SOA安全解决方案入手也是如此。

  弗雷斯特研究公司(Forrester)强烈建议,你设计的解决方案应当不需要应用程序开发人员编写与安全有关的代码。就算借助严格的指导准则和代码审查,从获得一致的安全性以及便于将来应用程序安全具有灵活性、可以不断改进来看,把安全性嵌入到应用程序代码中的做法都面临很高风险。要注意:不是说让开发人员不必为安全性编写代码,就用不着培训应用程序开发人员使用一套安全编码实践了。安全编码是应用安全实践的一个单独领域,涉及确保应用程序故障不会留下安全漏洞等问题。

  为你的安全策略找到适当组合的行业标准、产品、集成和框架是一个反复迭代过程,其中需要:

  1、确认安全需求

  对照一系列广泛、战略性的安全功能,评估自己的需求。这成了设计SOA安全策略和解决方案的基础。应根据你基于SOA的解决方案的主要设计重点来组织管理需求。弗雷斯特研究公司采用的一个模型按服务使用者、请求-响应、服务提供者以及安全需求来组织管理。在SOA安全设计的反复迭代过程中不断前进时,随着进一步了解标准、产品以及贵企业有没有能力为需求所带来的SOA安全支付成本,可能要重新考虑所选择的需求。

  2、确定所用的SOA安全规范

  你的SOA安全需求为确定可能哪几项SOA安全规范符合需求做好了准备。不过在选择你所要使用的实际规范时,必须考虑到自身基础架构中的产品(现有产品以及可能需要为SOA购买的产品)支持哪些规范。几种主要的规范包括:Web服务安全(WS-Security)、Web服务互操作性基本安全概要(WS-I Basic Security Profile)、XML加密(XML Encryption)和XML签名(XML Signature)等规范。几种高级的规范包括:Web服务信任(WS-Trust)、Web服务安全策略(WS-SecurityPolicy)、Web服务联合(WS-Federation)、XML访问控制标记语言(XACML)和Web服务安全通话(WS-SecureConversation)等规范。

  3、选择为你提供核心SOA安全功能的产品

  SOA安全解决方案的许多功能(比如使用Web服务安全标头来执行验证)可通过不同产品类别的多类产品来提供。你的设计过程必须考虑每一种选择,评估其优缺点,然后选择一款产品(或者一套相互协调的产品)来提供核心SOA安全功能。SOA安全解决方案有可能用到的关键产品类别包括:SOA硬件设备、SOA管理解决方案、企业服务总线、SOA安全服务器、应用服务器、安全令牌服务器、授权管理服务器以及身份和访问管理解决方案。

  4、配置及集成产品,以便协同工作

  你可能会有多个产品来执行某项特定的SOA安全功能;这些产品必须集成起来,以便协同工作。这项集成工作可能大部分由产品配置选项(比如对SOA硬件设备进行配置,把授权工作委托给某个单次登录产品)来完成,但也可能需要使用产品编程接口来构建集成组件。

  5、用框架填补漏洞

  产品集成工作完毕后,可能有必要为应用程序开发人员构建一个帮助框架,以便他们没必要在基于SOA的应用程序中编写安全代码。

  弗雷斯特研究公司建议使用反复迭代过程,主要有两个原因。首先,通常不是所有应用程序都需要满足你的所有安全需求;在构建SOA安全解决方案时,初期的轻型版应用程序也许基本上能够符合要求,而后期的应用程序需要为解决方案填充额外的功能。其次,每次你通过,就会加深了解如何利用现有的各部分内容来构建最有效的SOA安全解决方案。

  实施SOA方面处于领导地位的企业仍在为别人铺平道路。对一些企业来说,可能存在高级安全很重要的一种业务场景。这类企业可以证明有必要投入成本,来构建高级SOA安全解决方案。这些领导企业会在一路上帮助不断强化行业规范,并帮助厂商不断完善产品。如果贵企业眼下就需要高级SOA安全,市面上有许多产品和标准可以拿来使用,但要小心行事:你应当另外抽出时间,针对建立原型、产品调试以及性能和扩展性测试等方面进行相应的项目规划。

由生产者/消费者问题看JAVA多线程

2010年05月4日 11:27 上午  |  分类:Java技术

生产者消费者问题是研究多线程程序时绕不开的问题,它的描述是有一块生产者和消费者共享的有界缓冲区,生产者往缓冲区放入产品,消费者从缓冲区取走产品,这个过程可以无休止的执行,不能因缓冲区满生产者放不进产品而终止,也不能因缓冲区空消费者无产品可取而终止。

  解决生产者消费者问题的方法有两种,一种是采用某种机制保持生产者和消费者之间的同步,一种是在生产者和消费者之间建立一个管道。前一种有较高的效率并且可控制性较好,比较常用,后一种由于管道缓冲区不易控制及被传输数据对象不易封装等原因,比较少用。

  同步问题的核心在于,CPU是按时间片轮询的方式执行程序,我们无法知道某一个线程是否被执行、是否被抢占、是否结束等,因此生产者完全可能当缓冲区已满的时候还在放入产品,消费者也完全可能当缓冲区为空时还在取出产品。

  现在同步问题的解决方法一般是采用信号或者加锁机制,即生产者线程当缓冲区已满时放弃自己的执行权,进入等待状态,并通知消费者线程执行。消费者线程当缓冲区已空时放弃自己的执行权,进入等待状态,并通知生产者线程执行。这样一来就保持了线程的同步,并避免了线程间互相等待而进入死锁状态。

  JAVA语言提供了独立于平台的线程机制,保持了”write once, run anywhere”的特色。同时也提供了对同步机制的良好支持。

  在JAVA中,一共有四种方法支持同步,其中三个是同步方法,一个是管道方法。

  1. 方法wait()/notify()

  2. 方法await()/signal()

  3. 阻塞队列方法BlockingQueue

  4. 管道方法PipedInputStream/PipedOutputStream

  下面我们看各个方法的实现:

  1. 方法wait()/notify()

  wait()和notify()是根类Object的两个方法,也就意味着所有的JAVA类都会具有这个两个方法,为什么会被这样设计呢?我们可以认为所有的对象默认都具有一个锁,虽然我们看不到,也没有办法直接操作,但它是存在的。

  wait()方法表示:当缓冲区已满或空时,生产者或消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让另一个线程开始执行;

  notify()方法表示:当生产者或消费者对缓冲区放入或取出一个产品时,向另一个线程发出可执行通知,同时放弃锁,使自己处于等待状态。

  下面是一个例子代码:

  import java.util.LinkedList;

  public class Sycn1{

  private LinkedList<Object> myList =new LinkedList<Object>();

  private int MAX = 10;

  public Sycn1(){

  }

  public void start(){

  new Producer().start();

  new Consumer().start();

  }

  public static void main(String[] args) throws Exception{

  Sycn1 s1 = new Sycn1();

  s1.start();

  }

  class Producer extends Thread{

  public void run(){

  while(true){

  synchronized(myList){

  try{

  while(myList.size() == MAX){

  System.out.println(”warning: it’s full!”);

  myList.wait();

  }

  Object o = new Object();

  if(myList.add(o)){

  System.out.println(”Producer: ” + o);

  myList.notify();

  }

  }catch(InterruptedException ie){

  System.out.println(”producer is interrupted!”);

  }

  }

  }

  }

  }

  class Consumer extends Thread{

  public void run(){

  while(true){

  synchronized(myList){

  try{

  while(myList.size() == 0){

  System.out.println(”warning: it’s empty!”);

  myList.wait();

  }

  Object o = myList.removeLast();

  System.out.println(”Consumer: ” + o);

  myList.notify();

  }catch(InterruptedException ie){

  System.out.println(”consumer is interrupted!”);

  }

  }

  }

  }

  }

  }

Pages: 1 2 3 4 5 6 Next