随心

一个普通程序员的点点滴滴

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  100篇文章 :: 0篇收藏:: 50篇评论:: 0个Trackbacks

文章

收藏

相册

存档


正在读取评论……


2008年02月26日


    摘要:
     22号到北京芬兰大使馆去申请90天的商务签证了。比想象中的简单、快!签证的人很少。签证处有2个中秘窗口,2个面试窗口,一个财务窗口。给中秘递上资料,然后交钱,等了10分钟左右,签证官面试,问了些常规问题,主要就是看和资料上写的是否一致,大概4,5分钟就完了。感觉也没什么,这主要是和前美国比,最近公司有几个同事在成都美国领事馆签美国,都被拒了。其中有人被拒的理由是:在公司服务时间太短。看来美国签证的确难拿啊!!想到年前intel的朋友去美国开年会,他的同事也有被拒的,心里也就想的通了,连intel这样的美国大公司的员工都拒了,什么都有可能了。
     美国真的就那么好?比欧洲国家好?
    (全文共363字)——点击此处阅读全文


2007年12月27日


    摘要:最近在IBM的网站上看到一些有趣的东西,链接如下,方便自己以后查找

http://www.ibm.com/developerworks/cn/linux/l-lob800-1.html?S_TACT=105AGX52&S_CMP=NL&ca=dnl-cn-12192007    (全文共155字)——点击此处阅读全文


2007年09月11日


    摘要:----CVM启动和初始化过程    (全文共14009字)——点击此处阅读全文


2007年09月03日


    摘要:----CVM堆和代码执行    (全文共36535字)——点击此处阅读全文


2007年08月16日


    摘要:亲自的,当你接触一个新系统,第一件事是你想要搞清楚每一个东西是怎么结合在一起的。如果你像我一样是个虚拟思考者,最好的一条路就是画一个图表来说明你觉得重要的东西以及他们之间的联系。嵌入式系统的一个例子,以我的经验,知道内存里有什么在哪儿,系统资源是怎样使用的也同样重要,因此我画了一个数据结构的图表    (全文共18288字)——点击此处阅读全文


2007年08月10日


    摘要:严格的说,多任务意味着同一时间能做多个事情。对JAVA平台,这意味着能够有同时执行的代码。JAVA平台已经支持多任务。    (全文共37181字)——点击此处阅读全文


2007年08月06日


    摘要:----C特性和CVM    (全文共16139字)——点击此处阅读全文


2007年02月08日


    摘要:----什么时候JavaSE能成为比JavaME CDC更好的选择    (全文共4539字)——点击此处阅读全文


2007年01月30日


    摘要:the part 2 about PhoneME Advanced's VM    (全文共8266字)——点击此处阅读全文


2007年01月25日


    摘要:The part 1 that introduction of PhoneMe Advanced CDC VM     (全文共5614字)——点击此处阅读全文




    摘要:

            The article translate from Darryl Mocek's blog. Darryl Mocek is a staff engineer for sun microsystems,Inc. currently working on J2ME CDC and related techonlogies. the URL is : http://weblogs.java.net/blog/darryl_m/archive/2006/12/phoneme_advance_1.html

    &    (全文共583字)——点击此处阅读全文



2007年01月23日

           The article translate from Darryl Mocek's blog. Darryl Mocek is a staff engineer for sun microsystems,Inc. currently working on J2ME CDC and related techonlogies. the URL is : http://weblogs.java.net/blog/darryl_m/archive/2006/11/phoneme_advance.html

So, let's begging...

      在这篇文章里,我们将会谈到 PhoneMe 高级工程的目录结构。当你读到这篇文章的时候可以通过这里的链接浏览源代码。你也可以加入这个工程来做这个。

      PhoneME Advanced的源代码从 components/cdc/trunk 目录开始。在 trunk 目录下有下面的目录:

  • build  包含 make 文件
  • src   包含源代码
  • test  包含测试文件

这是显而易见的。

      一旦你在 src 目录,你就在所有平台源代码的根路径上了。你可以注意到有一个 share 目录包含有一系列的硬件和操作系统目录。我们将在后面谈到它。这些目录包含了特定硬件和操作系统的源代码(除了 share 目录)。下面的 share 目录里包含了大多数的 PhoneMe Advanced 的代码

  • appmanager  包含应用程序管理代码
  • basis   包含个人基本描述的代码
  • cdc    包含个人连接设备的演示代码
  • classes    包含个人连接设备的代码
  • foundation   包含基础描述的代码
  • javavm     包含 cvm 的代码
  • lib         包含java 安全文件
  • native    包含共享的本地代码
  • personal   包含个人描述的代码
  • tools        包含工具

        这些所有的目录都可以有一个类别:基层的,个人的。在这里最典型的是 classes 和 native 目录。classes 目录包含了所有的java代码,native目录包含了所有的本地支持代码。native目录豪华 JNI 代码和那些需要用到的库,比如 Qt

        appmanager 目录完全由java代码组成,没有包含本地代码。 cdc 目录只包含了演示代码,lib 目录包含了2个 text 文件来描述和java 安全有关的东西,一个策略文件和一个安全文件。tools 目录包含java代码和本地代码,但现在的目录结构有稍微的不同,现在我集中在 profile 代码。

       classes目录下面,大部分是 java package的根。所以你在下面能找到 java/lang 目录。

        CDC profile 建立在其他部分之上。所以 personal basis profile 包含了基础profile,personal profile 又包含了personal basis profile。 在这些目录中,foundation profile 代码包含在 foundation 目录。personal basis profile 包含在 personal basis目录中。在这些不同的目录中你可以找到一些相同命名的profile文件。比如:你可以在 basis/classes/common/java/awt/toolkit 下找到 toolkit.java 。在 personal/classes/common/java/awt/toolkit 下找到 toolkit.java 。这说明他们是不同系列的 profile 文件。

          在 build 目录下,你可以找到和 src 类似的目录结构。一个 share 目录,它包含了跨越所有平台的 make 文件。特定的目录对应特定的平台,下面的 make 文件都是对对应平台优化了的。





    摘要:

    Now, java is open source! I'm interested how the j2me implemented on the different platform, So i will join this open source project, learning more and more about j2me. j2me open source are named phoneme (this link will redirect you to java.net ,and you can register first). you can find all reference in this site.  let's go!

 &nbs    (全文共539字)——点击此处阅读全文



2007年01月22日

摘至IBM, 原文URL:http://www.ibm.com/developerworks/cn/opensource/os-linuxthinkpad/index.html?ca=dwcn-newsletter-opensource

 

级别: 中级

Nathan Harrington (haringtn@us.ibm.com), 编程人员, IBM

2007 年 1 月 15 日

通过修改内核以在受震动导致内核出现紧急情况时自动重置 Linux 膝上型计算机,让您的计算机处于受保护的状态。在内核空间和用户空间中实现震动检测算法,从而执行自动关闭并在特定动力条件得到满足时重新启动。

2003 年,IBM® 开始销售在商业操作系统中集成了加速度传感器及相关软件的 ThinkPad 膝上型计算机,以便在 ThinkPad 坠地时对硬盘进行保护。来自 IBM 和其他地方的富有魄力的计算机程序高手们已经为 Linux 内核开发了利用这些传感器的模块。膝上型计算机的屏幕显示方向、桌面切换、甚至是游戏控制和实时 3D 模型等特性均已实现。

2006 年中期,适用于 Linux 膝上型计算机的基于敲击的命令开始可用于用户空间 Perl 脚本(与内核空间中的基于 C 的代码相对),允许用户运行基于特定敲击序列的随机命令。本文描述了修改 Linux 内核以添加经常需要的功能的过程:对物理输入做出反馈。当 Linux 内核出现紧急情况时,用户可以震动计算机(或对膝上型计算机执行开发人员可配置的任意次数的物理移动),计算机将重置。

本文还介绍了在非紧急情况模式下执行正常关闭的方法。例如,如果用户不注意将计算机放在尚未拉好的计算机包中,则需要计算机检测到正常行走或开车的动作,并关闭计算机。

先决条件

硬件

许多在 2003 年以后(包括 2003 年)制造的 IBM ThinkPad 都配有 HDAPS 硬件。如果不能确定硬件配置,可以到 Lenovo 的 Web 站点中查看详细的技术信息。要运行以下代码,必须有 ThinkPad。某些 MacBook 配有加速度传感器及同样的通过内核访问这些传感器的通用方法。但是,此处的代码并未在 Apple 硬件上做测试,而是基于两个 IBM ThinkPad T42p 型号开发及测试的。有关如何查找在物理上支持膝上型计算机所需的 ThinkPad 硬件的链接,请参阅 参考资料

软件

本文假定您熟悉内核构建过程,并了解内核编译所带来的发行版间的不一致性。有关内核构建过程的简介,以及一些优秀的入门示例,请参阅 参考资料

从 kernel V2.6.15 起,HDAPS 驱动程序已经包含在 Linux 内核中。为了简单起见,请获取最新的内核程序。为了便于开发及管理,本文是基于 Fedora Core V5 开发的。下面用于设置内核构建环境的指导信息是专门针对 Fedora Core 的,但是一般原理适用于所有 Linux 发行版。





回页首


内核开发设置

内核配置、编译和测试

要修改内核,需要按照版本信息中的指导信息进行操作。打开 Web 浏览器并开始按照第 8.6 节:“Preparing for Kernel Development” 中的指导信息进行操作。执行到第 2 部分时,可能会在执行第二条命令 su -c 'yumdownloader --source kernel' 时遇到问题。如果该命令未能把 kernel-2.6.15-1.2054_FC5.src.rpm 软件包下载下来,请使用 wget 命令 wget ftp://ftp.linux.ncsu.edu/pub/fedora/linux/core/5/source/SRPMS/kernel-2.6.15-1.2054_FC5.src.rpm 来获取该软件包。

在执行步骤 5 时,请用 cp configs/kernel-2.6.15-i686.config .config 命令选择基本的 i686 默认配置。确保将 makefile 中的 EXTRAVERSION 部分从 -prep 更改为 -1.2054_FC5。用 make oldconfig 更新构建配置。然后用 su -c "yum install kernel-devel" 命令安装内核开发模块。该模块将用于编译紧急情况触发模块。

我们现在已经完成了 Fedora Core V5 Release Notes 文档中介绍的内核配置的相关部分。其余步骤都是所有内核构建过程通用的标准步骤。建议现在构建并安装新内核、模块和 RAM 磁盘设置以确保一切按预期运行。如果您对自己的新内核配置很有信心,可以跳过以下步骤并直接转到内核修改部分。

make 命令构建新内核。成功构建内核后,请用 su -c "cp ./arch/i386/boot/bzImage /boot/vmlinuz-2.6.15hdaps" 命令将其复制到 /boot 目录。您需要使用 su -c "make modules_install" 命令构建模块。最后一个构建步骤是用 su -c "/sbin/mkinitrd hdapsInitrd.img 2.6.15-1.2054_FC5" 命令为 HDAPS 内核创建 RAM 磁盘。用 su -c "cp hdapsInitrd.img /boot/" 命令将这个新的 RAM 磁盘复制到引导区。引导时,用以下行更新 grub.conf 文件:



清单 1. grub 配置
				
title Fedora Core (2.6.15hdaps)
    root (hd0,0)
    kernel /vmlinuz-2.6.15hdaps ro root=/dev/VolGroup00/LogVol00 rhgb quiet
    initrd /hdapsInitrd.img

修改 panic.c 和 hdaps.c

现在已经准备好开始一些可快速完成的内核配置。确保位于 ~/rpmbuild/BUILD/kernel-2.6.15/linux-2.6.15.i686 目录。一定要先包含 hdaps 模块作为内核的内置组件,从而准备好在计算机的运行模式中提供对各处的震动检查。

使用 make menuconfig 命令并选择 Device Drivers > Hardware Monitoring Support。键入 Y 以包含 Hardware Monitoring Support 模块,因为 HDAPS 模块依赖于此模块。滚动到清单底部,并在 IBM Hard Drive Active Protection System (hdaps) 条目的旁边再次键入 Y。退出菜单并保存配置。

打开 drivers/hwmon/hdaps.c 文件,然后将以下文本添加到 include 部分中:#include <linux/reboot.h>。并紧挨着 hdaps_read_pair 子程序后面添加下面的新子程序:



清单 2. 来自 hdaps.c 的完整的 panicShake 子程序
				
/*
 * panicShake - reboot the machine if shaken
 */
extern void panicShake(void)
{
 int ret, x, y; // return value and x,y from hdaps
 int int baseX = -5000; // off scale default values
 int baseY = -5000;
 int totalDev = 0; // running total of deviations from rest (shaking total)
 int devThreshold = 4000; // larger threshold for more shaking
 int dimShiftX = 150; // in case your users shake more in a certain dimension
 int dimShiftY = 150;

 while(1)
 {
  ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
  if (!ret)
  {
   if( x != 0 && y != 0 )
   {
    // if its a successful read and not a zero read
    if( baseX == -5000 )
    {
     baseX = x;
     baseY = y;
    }
    if( abs(baseX - x) > dimShiftX || abs(baseY - y) > dimShiftY )
    {
     totalDev += abs(baseX - x);
     totalDev += abs(baseY - y);
    }
    if( totalDev > devThreshold )
    {
     printk(KERN_EMERG "ok, ok! you're shaking my substrate - restarting");
     emergency_restart();
    }
   }//if not a zero value
  }//if successful read of hdaps data

 }//infinite while

}//panicShake

震动检测程序就绪后,需要在系统出现紧急情况时调用该检测程序。打开 kernel/panic.c 文件,并在紧挨着 panicBlink 条件部分之前的位置上放置一个对 panicShake(); 子程序的调用。发出 make 命令。趁着对内核进行重新构建时,让我们复查一下震动检测代码。首先,设置一些变量:



清单 3. panicShake 变量
				
 int ret, x, y; // return value and x,y from hdaps
 int baseX = -5000; // off scale default values
 int baseY = -5000;
 int totalDev = 0; // running total of deviations from rest (shaking total)
 int devThreshold = 4000; // larger threshold for more shaking
 int dimShiftX = 150; // in case your users shake more in a certain dimension
 int dimShiftY = 150;
 

需要特别注意的是偏差阈值参数和空间移位参数。这些参数可能需要根据尝试检测的动作的独特性质做出调整。例如,如果感觉迫切需要像完成篮球传球动作一样震动计算机,可尝试减少 dimShiftX 参数以更轻松地检测垂直于计算机屏幕的动作。反过来,如果震动脉冲触发剧烈的锯齿状动作,则考虑减少 dimShiftY 参数,以便快速地检测平行于屏幕的震动并在发生进一步的损害之前重置计算机。

空间参数选择 150 及总偏差选择 4000 都旨在检测一般用户的典型震动动作。要立即响应输入,请尝试将空间移位参数减少到 10 或更少,并将总偏差参数减少到 10 或更少。这些值将导致其他类型的输入被立即识别出来,例如猛击键盘或拍打显示器外壳。

接下来,考虑无限循环语句和条件。



清单 4. panicShake hdaps 读取和基本设置
				
 while(1)
 {
  ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
  if (!ret)
  {
   if( x != 0 && y != 0 )
   {
    // if its a successful read and not a zero read
    if( baseX == -5000 )
    {
     baseX = x;
     baseY = y;
    }

代码运行如下:其余时间里,从 Hdaps 传感器中读取当前加速度传感器读数。读数经常是不成功的或者两个值都等于 0,0,这是不能用的数据。需要避免这些虚假的 0,0 读数,来自传感器各个方向上的每 10 个读数中就会有一个读数是 0,0 —— 无效的数据,确实如此。如果是首次成功读取,则将基本参数设为第一个 x 值和 y 值。如果计算机被放在不平的表面(例如人的膝盖上)时发生紧急情况,这将允许我们更有力地检测震动或其他动作。

子程序的其余部分实现简单的震动检测算法。



清单 5. panicShake 震动检测
				
    if( abs(baseX - x) > dimShiftX || abs(baseY - y) > dimShiftY )
    {
     totalDev += abs(baseX - x);
     totalDev += abs(baseY - y);
     baseX = x;
     baseY = y;
    }
    if( totalDev > devThreshold )
    {
     printk(KERN_EMERG "ok, ok! you're shaking my substrate - restarting");
     emergency_restart();
    }
   }//if not a zero value
  }//if successful read of hdaps data

 }//infinite while

如果在任意方向上的空间移位大于我们先前设定的阈值,就按照两个方向上移动的量增加总偏差。然后将当前的基数设为现有的加速度级别。这样重复地重新初始化基数值要求用户持续超出空间移位值以增加检测到的总偏差。这允许用户在紧急模式下移动并存储 ThinkPad,从而安全地将机器送到系统管理员那里。如果仅需要侧立、倾斜和持拿 ThinkPad 以触发重新启动,请删除重新初始化设定。





回页首


测试 panicShake() 内核

要发动一种紧急情况,需要在内核中调用紧急情况子程序。创建以下 makefile:obj-m := panicCall.o,程序 panicCall.c 在编译时将使用该文件:



清单 6. panicCall.c 内核模块源代码
				
/*
 * panicCall.c - Instigate a kernel panic
 */
#include <linux/module.h> /* Needed by all modules */
#lincude <linux/kernel.h> /* Needed for KERN_INFO */

static char *pMesgStr = "PANIC SHAKE AND BAKE";

int init_module(void)
{
 printk(KERN_INFO,"panicCall module loaded\n");
 panic(pMesgStr);
 return(0);
}

void cleanup_module(void)
{
 printk(KERN_INFO,"panicCall module unloaded, beyond possible");
}

以超级用户身份用 make -C /lib/modules/$(uname -r)/build SUBDIRS=$PWD modules 命令编译 panicCall 模块。现在就有了一个可调用的模块可以使用 insmod panicCall.ko 命令触发紧急情况。如果还没有该模块则重新引导(以激活 hdaps 紧急情况下触发启用震动的内核),并运行 insmod panicCall.ko。应当会看到类似以下内容:



清单 7. 内核紧急情况堆栈
				
panicCall: module license 'unspecified' taints kernel.
Kernel panic - not syncing: PANIC SHAKE AND BAKE ACTIVE
 [<c011a32e>] panic+0x3e/0x174   [<f8a97017>] init_module+0xb/0xc [panicCall]
 [<c013050a>] sys_init_module+0x1382/0x1514   [<c0152413>] do_sync_read+0xb8/0xf3
 [<c012a17f>] autoremove_wake_function+0x0/0x2d   [<c01c0672>]
 	 _atomic_dec_and_lock+0x22/0x2c
 [<c0169c32>] mntput_no_expire+0x11/0x6d   [<c0102bc1>] syscall_call+0x7/0xb

现在拿起计算机,然后用力地晃动它,计算机将打印出 “shaking substrate” 消息并执行重新启动。如果您不希望晃动可能活动的磁盘驱动器,请以超级用户身份发出以下命令:



清单 8. RAM 磁盘创建和模块复制
				
mkdir /tmp/ramdisk0
mke2fs /dev/ram0
mount /dev/ram0 /tmp/ramdisk0/
cp /root/panicCall.ko /tmp/ramdisk0/
cp /sbin/insmod /tmp/ramdisk0/

现在有了将模块插入位于 RAM 磁盘的内核所需的两个文件。用以下部分更新 /etc/init.d/halt 脚本,将其放在刚好位于 fsck check 部分之下 halt execute 部分之上的位置:



清单 9. 修改 /etc/init.d/halt
				
echo "disks now mounted in readonly mode, spin down in 5 seconds";
/sbin/hdparm -S 1 /dev/hda
echo "spin down hda called, waiting 10 seconds";
sleep 10
echo "calling panic from ramdisk location";
/tmp/ramdisk0/insmod /tmp/ramdisk0/panicCall.ko

以超级用户身份执行命令 init 0 以将计算机转入关闭模式中。在调用关闭程序前,计算机将把紧急情况触发模块装入内核,并调用震动检测程序。如果在系统关闭时仔细听硬盘的声音,可以听到明显比以往更长的喀哒声,然后多普勒磁盘将随着机械臂逐渐下降的 “积载” 位置而降低并且磁盘旋转停止。再过大约五秒钟后,将从 RAM 磁盘执行紧急情况模块,而物理磁盘头仍停止不动。现在,您可以随心所欲地晃动 ThinkPad 而无需考虑磁盘的运行状况。





回页首


用户空间关闭和动作检测

很多 IT 管理员都十分怀念能够随时获知硬件物理历史记录的功能。使用同一个简单的震动检测算法、一个 Perl 脚本和一种监视策略,管理员将能够更好地跟踪硬件的状态。例如,使用下面的 Perl 脚本在计算机遭到用户震动时平稳地关闭计算机。根据用户对 ThinkPad 的操作发送一封电子邮件、闪烁 “ThinkLight” 或播放一个声音文件,这些都可以轻松地完成。



清单 10. 用于检测震动的 Perl 脚本,第 1 部分
				
#!/usr/bin/perl -w 
# shakeShutdown.pl - shutdown (or other command) when the computer is shaken
use strict;
my $file = "/sys/devices/platform/hdaps/position";
my $baseX = -5000;
my $baseY = -5000;
my $totalDev = 0;
if( @ARGV != 1 ){ die "specify a threshold value" }
my $devThreshold = $ARGV[0];
my $dimShiftX = 150;
my $dimShiftY = 150;
while(1)
{
 open(HD,"$file") or die "can't open file";
  my $line = <HD>;
  chomp($line);
  $line =~ s/\(//g;
  $line =~ s/\)//g;
  $line =~ s/\,/ /g;
  my( $x, $y ) = split " ", $line;

正如您所见,初始的程序设置几乎与 hdaps 内核代码完全相同。正则表达式和 split 命令仅将 x 值和 y 值从 (5,4) 更改为 5 和 4。程序的其余部分实质上也是相同的:



清单 11. 用于检测震动的 Perl 脚本,第 2 部分
				
  if( $x != 0 >> $y != 0 )
  {
   if( $baseX == -5000 )
   {
    $baseX = $x;
    $baseY = $y;
   }
   if( abs($baseX - $x) > $dimShiftX || abs($baseY - $y) > $dimShiftY )
   {
    $totalDev += abs($baseX -$x);
    $totalDev += abs($baseY -$y);
    $baseX = $x;
    $baseY = $y;
   }
   if( $totalDev > $devThreshold )
   {
    print "threshold passed $totalDev\n";
    my $res=`/sbin/shutdown -h 1`;
   }
  }
 close(HD);
}

请注意 shutdown -h 1 命令。这将给用户提供 60 秒的时间更改方法并发出关闭中止。更改此命令以运行您最喜欢的邮件程序,用户滥用设备时可以让系统管理员知道此情况。将消息记录到系统日志中,或让 PC 扬声器发出声响以便对获得的物理输入发出即时用户反馈。用 perl shakeShutdown.lp 1000 命令运行脚本。偏差阈值变得更小,因为加速度传感器的每次读取间隔与内核空间的每次读取间隔比较而言减少了。

修改空间移位参数和偏差阈值可以提供有益的对内核空间外部的物理活动的额外监视。例如,要采集 “行走” 行为的数据,需要将空间移位参数设为大约 20,并将偏差阈值设为大约 5000。这将检测到大约 63 个双坐标轴空间移位,这与膝上型计算机在处于运行状态时被放在典型的单肩背膝上型计算机包中的情况一致。检测到这种长距离行走后(不同于从办公位置到会议室的短距离行走),计算机将进入关闭程序以避免过热,因为空气在背包中不流通。修改空间移位参数使其具有高灵敏度,任何较大的撞击、坠落或震动都会被记录下来。





回页首


结束语

通过使用针对用户空间和内核级代码的这些简单算法,现在能够检测、记录和响应来自用户的各种物理输入。使用这些代码示例,从根据连续的加速度计算出来的高度修改硬盘性能参数,到丈量从办公位置到会议室的距离,并将其用邮件发送给空间规划师,您都可以应对自如。



参考资料

学习

获得产品和技术
  • Fedora Core V5 发行版的内核中包括 hdaps。

  • 使用 IBM 试用软件 改进您的下一个开放源码开发项目,这些软件可以通过下载或从 DVD 中获得。


讨论


关于作者

 

Nathan Harrington 是 IBM 的编程人员,目前从事 Linux、WatchPad 1.5 和资源定位技术的工作。





    摘要:

摘至IBM。原文url :http://www.ibm.com/developerworks/cn/java/j-javares.html?ca=dwcn-newsletter-java

对于 Java™ 语言开发人员来说,信息过量是一个真正的问题。每个新入行的程序员都要面临一个令人畏缩的挑战:要进入的行业是一个具有海量知识的行业。要了解的东西简直太多了。对于有经验的老手来说,情况只有些微好转。知识量总在增大,仅仅跟上进度就是一个挑战。如果有一份专业人士必备的书籍和网站列表该有多好!本文就是这个列表。它包含了每个专业的 Java 语言程序员在书架或浏览器书签中必备的最重要的书籍和网站。