五千年(敝帚自珍)

主题:【评论】Sun发布了最新的Java版本-- 5.0 Tiger版 -- Highway

共:💬18
分页树展主题 · 全看首页 上页
/ 2
下页 末页
  • 家园 【评论】Sun发布了最新的Java版本-- 5.0 Tiger版

    注意是5.0,而不是1.5。Sun有意的改变了Java版本的命名规则,以表示这是java历史上的一次突破。

    在Sun的发言中,有这么一段很有趣:

    Sun achieved record results for the SPECjbb 2000 benchmark (Standard Performance Evaluation Corporation Java Business Benchmark 20001) with JDK 5.0 running on a 2.4GHz Sun Fire V20z server, based on AMD64 Opteron processors. The configuration delivers 59,648 JBB operations per second on the SPECjbb 2000 on a 64-bit two-way system, beating the best previously announced 64-bit two-way system results by 9 percent. Furthermore, the tests indicate Sun has the capacity to support more warehouses than any other two-way system, having demonstrated the ability to support 80 warehouses. This is 10 times the amount typically run on a two-way system.

    点看全图

    外链图片需谨慎,可能会被源头改

    Sun的这一个记录不是在自己的Sparc 机器 + Soloris操作系统上创造的,而是在AMD芯片的机器上创造的。如果你留意一下就会发现,SPECjbb 2000 单处理器/双处理器的纪录已经被AMD牢牢占领。

    看来,AMD确实有了实质性进步!

    • 家园 Eclipse 3.0 Build 20040715开始支持JDK5

      今天我下载了Eclipse 3.0 Build 20040715,发现它开始支持JDK 5.0了。但是目前的版本虽然支持了Generic Programming,却不支持Boxing/Unboxing。也就是说,虽然你可以用Javac正常编译使用了Boxing/Unboxing特性的源程序,但是该源程序在Eclipse 3.0 Build 20040715环境中却会被报告错误。

      下面是我曾经列表过的三个源程序在Eclipse 3.0 Build 20040715环境中能够通过的对应版本,有心者可以对比一下:

      第一个源程序:

      package myPackage;

      import java.util.*;

      public class Freq

      {

      public static void main(String[] args) {

      Map<String, Integer> m = new TreeMap<String, Integer>();

      for (String word : args) {

      Integer freq = m.get(word);

      m.put(word, new Integer((freq == null ? 1 : freq.intValue() + 1)));

      }

      System.out.println(m);

      }

      }

      第二个源程序:

      package myPackage;

      import java.util.*;

      public class MyClass {

      public void test()

      {

      ArrayList<String> al=new ArrayList<String>();

      al.add("111");

      al.add("222");

      System.out.println(al.get(al.size()-1));

      System.out.println(al.get(al.size()-2));

      ArrayList<Integer> al2=new ArrayList<Integer>();

      al2.add(new Integer(111));

      al2.add(new Integer(222));

      System.out.println(al2.get(al2.size()-1));

      System.out.println(al2.get(al2.size()-2));

      }

      public static void main(String[] args) {

      MyClass mc=new MyClass();

      mc.test();

      }

      }

      第三个源程序:

      package myPackage;

      class BasicGeneric <A>

      {

      private A data;

      public BasicGeneric(A data)

      {

      this.data = data;

      }

      public A getData()

      {

      return data;

      }

      }

      public class MyClass2 {

      public String test01(String input) {

      String data01 = input;

      BasicGeneric<String> basicGeneric = new BasicGeneric<String>(data01);

      String data02 = basicGeneric.getData(); return data02;

      }

      public int test02(int input) {

      Integer data01 = new Integer(input);

      BasicGeneric <Integer> basicGeneric = new BasicGeneric<Integer>(data01);

      Integer data02 = basicGeneric.getData();

      return data02.intValue();

      }

      public static void main(String [] args) {

      MyClass2 sample = new MyClass2();

      System.out.println(sample.test01("This generic data"));

      System.out.println(sample.test02(12));

      }

      }


      本帖一共被 1 帖 引用 (帖内工具实现)
    • 家园 Java 1.5的Boxing/UnBoxing是如何实现的

      下面这个例子(源程序和反编译程序)说明了Java 1.5的Boxing/UnBoxing是如何实现的,以这样的方式,它的性能不可能有任何提高。

      源程序:

      import java.util.*;

      public class Freq

      {

      public static void main(String[] args) {

      Map<String, Integer> m = new TreeMap<String, Integer>();

      for (String word : args) {

      Integer freq = m.get(word);

      m.put(word, (freq == null ? 1 : freq + 1));

      }

      System.out.println(m);

      }

      }

      编译以后,又反编译出的程序:

      import java.io.PrintStream;

      import java.util.Map;

      import java.util.TreeMap;

      public class Freq

      {

      public Freq()

      {

      }

      public static void main(String args[])

      {

      TreeMap treemap = new TreeMap();

      String args1[] = args;

      int i = args1.length;

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

      {

      String s = args1[j];

      Integer integer = (Integer)treemap.get(s);

      treemap.put(s, Integer.valueOf(integer != null ? integer.intValue() + 1 : 1));

      }

      System.out.println(treemap);

      }

      }

      评论:所谓的Boxing/Unboxing不过是自动做到以前需要手工编码来完成的转换,而没有任何新的东西。这样的进步,确实有可能提高程序员的编程效率,但是绝不可能提高程序的运行性能,因为它没有任何实际的改进。另外,可以注意一下所谓改进的循环是如何实现的,那不过是个简单的展开。

      • 家园 Java 也support template了?

        看老兵的code,有此疑惑?

        • 家园 Sun将在Java 1.5或者JDK 5.0中提供此Feature

          到目前为止,还不知道将来是Java 1.5还是JDK 5.0,因为网页上写的是JDK 5.0,而下载的软件里面却是Java 1.5,实在是有趣,这里还是统称为Java 1.5算了,管它以后叫什么。

          我刚才试验了一下,Java 1.5里面的枚举是用类实现的,可以有自己的构造函数以及set/get函数,这意味着它也有类的开销。

          实在是不明白为什么Sun不能够提供一种轻量级的类变种?因为对于枚举这样的简单类型来说,完整的类开销是不必要的,虽然用类来实现枚举是很简单的事情。

    • 家园 Java 1.5的Generic是如何实现的

      今天忽然有兴趣,写了两个很简单的Java 1.5程序,用Java 1.5来编译,然后用DJ来反编译所生成的Class文件,以此试试它的Generic是如何实现的,发现整个一个坑蒙拐骗。下面是各自的源程序和反编译出来的程序以及有关说明。

      第一个程序的源程序:

      import java.util.*;

      public class MyClass {

      public int sum(int data1,int data2) {

      return data1 + data2;

      }

      public void test()

      {

      ArrayList<String> al=new ArrayList<String>();

      al.add("111");

      al.add("222");

      System.out.println(al.get(al.size()-1));

      System.out.println(al.get(al.size()-2));

      ArrayList<Integer> al2=new ArrayList<Integer>();

      al2.add(111);

      al2.add(222);

      System.out.println(al2.get(al2.size()-1));

      System.out.println(al2.get(al2.size()-2));

      }

      public static void main(String[] args) {

      MyClass mc=new MyClass();

      System.out.println(mc.sum(10,20));

      mc.test();

      }

      }

      对应的反编译程序:

      import java.io.PrintStream;

      import java.util.ArrayList;

      public class MyClass

      {

      public MyClass()

      {

      }

      public int sum(int i, int j)

      {

      return i + j;

      }

      public void test()

      {

      ArrayList arraylist = new ArrayList();

      arraylist.add("111");

      arraylist.add("222");

      System.out.println((String)arraylist.get(arraylist.size() - 1));

      System.out.println((String)arraylist.get(arraylist.size() - 2));

      ArrayList arraylist1 = new ArrayList();

      arraylist1.add(Integer.valueOf(111));

      arraylist1.add(Integer.valueOf(222));

      System.out.println(arraylist1.get(arraylist1.size() - 1));

      System.out.println(arraylist1.get(arraylist1.size() - 2));

      }

      public static void main(String args[])

      {

      MyClass myclass = new MyClass();

      System.out.println(myclass.sum(10, 20));

      myclass.test();

      }

      }

      评论:注意它对类和初始类型的不同处理。

      第二个程序的源程序:

      这是一个Generic类

      public class BasicGeneric <A>

      {

      private A data;

      public BasicGeneric(A data)

      {

      this.data = data;

      }

      public A getData()

      {

      return data;

      }

      }

      它的使用者:

      import java.util.*;

      public class MyClass2 {

      public String test01(String input) {

      String data01 = input;

      BasicGeneric<String> basicGeneric = new BasicGeneric<String>(data01);

      String data02 = basicGeneric.getData(); return data02;

      }

      public int test02(int input) {

      Integer data01 = new Integer(input);

      BasicGeneric <Integer> basicGeneric = new BasicGeneric<Integer>(data01);

      Integer data02 = basicGeneric.getData();

      return data02;

      }

      public static void main(String [] args) {

      MyClass2 sample = new MyClass2();

      System.out.println(sample.test01("This generic data"));

      System.out.println(sample.test02(12));

      }

      }

      各自对应的反编译程序:

      public class BasicGeneric

      {

      public BasicGeneric(Object obj)

      {

      data = obj;

      }

      public Object getData()

      {

      return data;

      }

      private Object data;

      }

      import java.io.PrintStream;

      public class MyClass2

      {

      public MyClass2()

      {

      }

      public String test01(String s)

      {

      String s1 = s;

      BasicGeneric basicgeneric = new BasicGeneric(s1);

      String s2 = (String)basicgeneric.getData();

      return s2;

      }

      public int test02(int i)

      {

      Integer integer = new Integer(i);

      BasicGeneric basicgeneric = new BasicGeneric(integer);

      Integer integer1 = (Integer)basicgeneric.getData();

      return integer1.intValue();

      }

      public static void main(String args[])

      {

      MyClass2 myclass2 = new MyClass2();

      System.out.println(myclass2.test01("This generic data"));

      System.out.println(myclass2.test02(12));

      }

      }

      评论:注意它是如何处理Template的!

      这就是Java 1.5的Generic Programming,什么玩意儿啊!

      • 家园 老兵先不忙下结论。也许是DJ的问题呢?

        把测试搞得大一些,看看性能有没有提高。因为使用了Generics应该避免了Casting(Boxing和Unboxing),因该有性能上的提升。

        我先回家吃饭去了。

        • 家园 回复

          DJ所作的只是把Byte Code反编译成Java Source Code,只要逻辑上对,它是不可能错的。

          我的例子说明了Java所谓的Generic不过是用Object这个始祖类来做障眼法,这样既可以保证对以前程序的兼容性,又可以以最简单的方式实现所谓的Generic,所牺牲的只是Generic思想。

          因此,Java 1.5的性能有可能有所提高,但是绝不是来自Generic。

          • 回复
            家园 我修改了一下你的程序,比如:

            ...

            ArrayList<String> al=new ArrayList<String>();

            al.add("111");

            al.add("222");

            al.add(new Integer(10));

            ...

            结果在编译的时候,compiler指出了错误。

            symbol  : method add(java.lang.Integer)
            location: class java.util.ArrayList<java.lang.String>
                       al.add(new Integer(10));
                         ^

            假如你的推断是正确的话(DJ did right job),那么java 5 改进的只是Compiler,Compiler检查过syntax后,又回到老路子去了。Is that what you are trying to say?

            • 家园 对,就是那么回事

              Java 1.5改进的只是它的Compiler,具体实现和以前的毫无二致,这样JVM就不需要任何修改,而能够实现语法上的Generic了。

              整个一个障眼法。

              平心而论,Java的Generic和C++的Template实现思路是类似的,就是通过预编译来实现语法上的需要(类型待定),而实际代码中依然还是确定的东西。但是C++的Template在预编译以后得到的是具体确定的类型,而Java的Generic在预编译以后得到的却是那个始祖类而不是具体的那个类型,这样Generic/Template的思想就被改变了,因为二者的Generic范围是截然不同的。Template可以做到比较严格的限定(就像是.Net 2.0中做到的那样),这样编译器可以帮助程序员发现可能出错的地方;而Generic却是毫无限定,编译器只是简单地应付交差了事。

              这就是为什么我说Java 1.5的Generic实现不怎么样的缘故,因为在三个实现Template的主流编程语言中(C+,C#和Java),它的实现是最差的。

              • 家园 老兵这段有专家水准。几个月前,我看过一片文章,和你的意思很接近

                这是微软MSDN杂志上的一片文章,我摘一段下来:

                [SIZE=3]How Does the Compiler Handle Generic Types?[/SIZE]

                Both C++ templates and the proposed generics equivalent in the Java language are features of their respective compilers. These compilers construct code from references to the generic or template type at compile time. This can cause code bloat as well as reduced type equivalence from one construction to another, even when the type arguments are the same. In contrast, CLR generics do not work this way.

                Generics in the CLR are a first-class feature of the platform itself. To implement it this way required changes throughout the CLR including new and modified intermediate language instructions, changes to the metadata, type-loader, just-in-time (JIT) compiler, language compilers, and more. There are two significant benefits to the run-time expansion in the CLR.

                First, even though each construction of a generic type, such as Node<Form> and Node<String>, has its own distinct type identity, the CLR is able to reuse much of the actual JIT-compiled code between the type instantiations. This drastically reduces code bloat and is possible because the various instantiations of a generic type are expanded at run time. All that exists of a constructed type at compile time is a type reference. When assemblies A and B both reference a generic type defined in a third assembly, their constructed types are expanded at run time. This means that, in addition to sharing CLR type-identities (when appropriate), type instantiations from assemblies A and B also share run-time resources such as native code and expanded metadata.

                Type equivalency is the second benefit of run-time expansion of constructed types. Here is an example: referencing code in AssemblyA.dll that constructs Node<Int32> and referencing code in AssemblyB.dll that constructs Node<Int32> will both create objects of the same CLR type at run time. This way, if both assemblies are used by the same application, their constructions of the Node<T> type resolve to the same type and their objects can be exchanged freely. You should note that compile-time expansion would make this logically simple equivalency either problematic or impossible to implement.

                There are a few other benefits to implementing generics at the runtime level, rather than at the compiler level. One such benefit is that generic type information is preserved between compilation and execution and is therefore accessible at all points in the code lifecycle. For example, reflection provides full access to generics metadata. Another benefit is rich IntelliSense&reg; support in Visual Studio&reg; .NET as well as a clean debugging experience with generic code. In contrast, Java generics and C++ templates lose their generic identity by run time.

                Another benefit, and mainstay of the CLR, is cross-language use―a generic defined using one managed language can be referenced by code written in another managed language. Meanwhile, the likelihood that a language vendor will put generics support in their compilers is increased by the fact that much of the hard work is done in the platform.

                Of all the fringe benefits of run-time type expansion, my favorite is a somewhat subtle one. Generic code is limited to operations that are certain to work for any constructed instantiation of the type. The side effect of this restriction is that CLR generics are more understandable and usable than their C++ template counterparts. Let's look at the constraints around generics in the CLR.

                • 家园 多谢夸奖

                  我以前也看到过一篇类似的文章,不过不是在微软的地盘上,而是在Java Community,抱歉想不起来具体的链接了。在那篇文章里,作者以一个C++ Guru的姿态来评论Java 1.5的Generic实现,并且有类似的描述。不过那时候Java 1.5还处于很早的时期,我希望等到正式版出来的时候事情会有所改进,不料都到Beta2了,它的实现还是这个样子。

    • 家园 还只是Beta 2,我还以为正式版出来了呢

      叫1.5还是5.0区别不大,关键是有多少真正的新东西,和什么时候主流Java工具厂商支持它,否则意义不大。

      关键在于,什么时候Java能够出现真正的本机代码编译器,否则性能上很难和.Net竞争,更不要说和C++程序相比较。

      另外在语言特性上,Java曾经比C#强一些,现在则基本倒过来了。

      按照这样的趋势,Sun还是交出Java的控制权算了。

      • 家园 Sun 这回心急了一些。不过到了beta2,主要东西就大差不差了。

        Java走向何方是个两难的选择。如果要和.NET竞争,那就要不断的增加features,而这样做又违背了java的初衷 -- Simplicity。网上有不少人对这种趋势深表忧虑,这样下去Java不就是又一个C++了吗?

        至于性能,抛开图形部分不说,Java喝.NET各有千秋。.NET在数据库操作上有一些优势。不过我的Benchmark用的是SQL Server,可能让.NET占了些便宜!

分页树展主题 · 全看首页 上页
/ 2
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河