阅读更多

3顶
0踩

编程语言

转载新闻 JVM 最简生存指南

2014-03-15 00:20 by 资深记者 学良3 评论(6) 有13560人浏览
本文由Grey翻译自hadihariri。作者希望能够通过这个指南来帮助新手在学习Java时少走一些弯路。

为什么要写这个指南

当你开始接触一个新的平台时,都会从做同一件事开始,通常你会根据你已学的概念或者框架来尝试快速搭建它,但是你无从下手,因为它们通常以全新的名字和方法展现在你面前。走完这个过程非常耗时,有时甚至让人一筹莫展。这篇指南正是用来帮助那些新手避免此类问题的。

这篇指南我也可以受益, 因为我确定我已经有了错误并且会发现更多的错误,所以你发现任何错误请及时反馈给我。最好的方式是给我发送pull request

目标人群

这篇指南主要是针对想学Java的.NET开发者,因为在这里你会发现诸多可以拿来和.NET进行比较的地方。其实从本文的URL你就可以看出些端倪了。话虽如此,我同样也希望这些能对那些初次接触Java平台的非.NET发开者有所帮助。

基础

Java语言,Java环境,Java虚拟机

这三者全完不是一回事。一个是编程语言(想想C#),一个是编程环境(想想.NET开发环境), 另一个则是开发平台(想想CLR)。

不幸的是似乎Java通常被用来指代以上所有。

不要一条路走到黑。虽然我不喜欢Java这样的语言但是整个Java的生态系统却充满了活力同时有许多创新不断发生。作为一名.NET开发者,你应该对NHibernate,NUnit,NLog,NAnt等等非常了解,其实 所有这些都来自于Java的生态系统(把N去掉就是了)。

多语言平台

把JVM想象是CLR。它们是对多语言编程提供跨平台的虚拟机。虽然它们都支持多语言,但是它们之间还是有差别的。
在CLR上,我们主要使用C#,VB.NET(“濒危物种”)和F#,在JVM上就是Java,Scala,Clojure, Ceylon,Groovy,JRuby和Kotlin,这里只是举几个例子

JVM字节码

JVM字节码是基于JVM的语言的编译从而在JVM上运行。这和.NET上的IL相似。

跨平台

JVM是100%跨平台的。除了Windows,OSX和Linux,它也可以在许多其它设备上运行。

JVM部署,版本类型和升级版本

JVM有多种实现。最常见的就是在Oracle和OpenJDK中的实现。甚至有一种.NET实现叫做IKVM.NET

版本类型和升级版本

这可能是目前为止在本指南中最复杂的部分。你根本无法想象连像命名或者版本控制这样简单的事情都能搞砸。这种命名方式甚至使微软的产品都显得合理不少。

让我们开始吧:

版本类型

  • JRE – Java运行环境。这是用来运行Java应用程序的。但你不能仅仅依靠它来开发运行在JVM上的应用程序。
  • Java SE (JDK) – Java标准版。它也称为JDK。这是在JVM上开发应用程序最起码的条件。
  • Java EE – Java企业版。好了,看名字你就懂了。通过它,你可以获得所有有关企业级分布式的东西大规模应用。明确一点的是它包含了Java SE。
  • Java ME – Java移动版。这是针对移动电话和便携设备的,它很像.NET微框架。
  • JavaFX – 代替了Swing,它是Java的主要GUI开发包。同时它(尽管有些争议的话题)也面向RIA的开发。(难道是HTML/JS/CSS不够好吗?)。
可以推断,所有形如Java XY的版本都可以写成JDK的形式。

这里你可以找到更多相关的历史命名

升级版本

当前的Java版本是7,Java 8 将于2014年发布。(译者注:Java 8将于2014年3月18日正式发布)

查询你所安装的Java版本和类型

java -version


你将会得到如下信息:

java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

这就是Java 7

为什么这么称呼?非常简单,将1.7.0_40中的1去掉就是7.0_40。其中0_40表示的是更新包。这是Java 7的所有版本发布

以此类推1.5是Java 5,1.6是Java 6,1.7就是Java 7,所以你猜测一下就知道,Java 8将会是 1.8。

是的,反正我是知道的。

安装Java

一旦你找到了你想要学习的版本,你可以去Oracle的安装指南页面进行下载安装。

如果你想要知道为什么你需要安装Ask Toolbar,不要怪Oracle。显然这是在它和Sun之前达成的协议。我听说一旦期满他们就不会继续履行协议。

应用程序输出又叫Artifacts

无论在.NET上还是在本地应用程序上,编译通常以得到一个可执行文件或者一些动态链接库文件来标志着结束。 而通过Java,你将在输出文件夹中得到若干.class文件。

通常每个类对应一个Java类(当编译Java语言或者其它语言时按照约定转化为字节码)。

这些类是JVM字节码,这非常类似于CLR中的IL。

JAR文件

类文件不会万年不变,你完全可以创建一个JAR文件,只不过就是一个.class文件的压缩包而已。你可以通过你最喜欢的工具来创建JAR文件,或者更简单的方式就是运行

jar cf jar-file input-file(s)


jar工具附带在JDK中(/bin文件夹下)。

WAR文件

WAR文件就是一个由Sun公司创造的面向网络应用的JAR文件。它包含了许多类文件和一些附加的元数据以及描述网络服务器(如TomCat)的文件夹。

运行Java应用程序

任何Java程序只能有一个主类在命令提示符中运行。例如:

java <class_containing_main_method>


你必须在拥有.class的文件夹下运行这段代码。

Classpath

在运行应用程序时,JVM在当前文件夹下寻找所有必要的依赖文件,然后再查找CLASSPATH环境变量所指向的一个或多个文件夹下的.class文件或者JAR文件和ZIP文件。

你可以设置CLASSPATH全局环境变量,当运行一个应用程序时通过使用Java命令并添加一个命令行参数:

java <class_containing_main_method> -cp <class_path>


每个条目都是用分号隔开的。

构建工具

.NET中有许多构建工具包括MS Build,NAnt,Albacore,Fake等等。JVM也没示弱。虽然许多语言都有它们自己的构建工具例如Clojure中的或者Scala中的SBT,许多语言(包括前面所提到的)可以使用更加标准的构建工具。

Ant

它是XML,NAnt也基于它。这就像MS-Build,尽管它只是XML我仍要强调它。

Maven

Maven非常流行。当你发现项目中有一个pom.xml文件,那这个项目就是Maven了。Maven也会损坏。Maven也是XML。

然而,Maven不仅仅是一个构建工具。它是一个封装系统。这就像.Net中的NuGet,也像Node.js中的NPM。像nuget.org,其实也有maven.org。这类似于“如果不用nuget.org就无法运行”,这种情况在Java系统中也同样存在。

NuGet,你也可以创建你自己的Maven版本库。Artifactory就能让你这么做。

Gradle

Gradle是一个更好的Maven。它基于Groovy所以你可以摆脱复杂的XML并且创建一个更好的依赖关系管理的方法。

我正在尝试更多的使用Gradle。

IntelliJ IDEA的构建

虽然IDE更多的是属于工具部分,IntelliJ IDEA也提供了它自己的构建系统。然而你仅仅能够在合适的环境下使用它,也就是IntelliJ IDEA和TeamCity的环境。

框架和库

这里有大量的框架和库,我只会对我已经知道的或者我需要的部分进行介绍。如果你有更好的推荐,请给我发一个pull request

JSON序列化

Jackson – 我用过它,感觉很好。

单元测试

相当多的单元测试框架:

  • JUnit – 作为事实上的标准,它相当不错,并且被众多工具支持。
  • Spek – 放弃。这是我自己的框架,但我仍然在用,值得一提。它能更好地支持DSL,至少我这么认为。
  • JBehaveDan North的原始JBehave框架。
  • TestNG – JUnit的替代品。我用的不多,所以不过多评论。

模拟框架

最近我也没模拟什么框架,但是我我曾经用过一个:

Mockito

日志

SLF4J – 这是在JVM平台上用于记录日志最常见的方式。使用它可以让你(理论上)变更日志并且允许选择你所需要的库。

IoC容器

  • Guice – 来自Google,我用过它,相当不错。
  • Spring – 来自Spring框架,我不确定你是否可以不用配置XML就使用它,因为我也没用过。

HTTP客户端

我正使用标准的Apache Commons,也接受更好的选择。

Apache的HTTP客户端 – 我正在使用它。非常需要一个封装器(Wrapper)。

Web框架

许多的Web框架都基于Java Servlet API的通用接口。这类似于OWIN.

应用可以托管在GlassFishJettyApache TomCat上。

顺便说一下,Oracle宣布它将停止对GlassFish商业版的支持,它的主要传播者,Arun Gupta,最近离开Oracle去了RedHat。现在它让WildFly来作为替代

对于Web开发而言,一个非常时髦而且轻量级的选择是Vert.x。它基于Netty的基础上构建的,你甚至可以使用不同的语言,如Java, JavaScript, Ruby。

网络

Netty – 高效的异步事件驱动框架来编写高性能的web应用程序。它是从通信层抽象出来的,所以你可以使用HTTP,Sockets等等。

其它库和工具

  • JodaTime – Java中时间和日期的管理比.NET还要脆弱。使用JodaTime可以有效解决这个问题。这起源于Jon Skeet的NodaTime
  • Reflections – 使反射更加完美。
  • Apache Commons – 许多经常用到的小型库。

约定

虽然约定在很大程度上是根据你选择的编程语言来决定,但是或多或少都有一些共同的约定。

命名空间

命名空间是逆序的,换言之,它以顶级域名开始,然后才是公司/组织域名等。

org.hadihariri.spek.runners


不幸的是,某些时候,它取决于每段是否成为了一个文件夹。那意味着最终你会在GitHub得到:



幸运的是如果你使用了一个不错的IDE,这些都不是问题而且易于管理。

属性和方法名称

如果你原来是学C#的,而现在正在使用像Java,Scala或者Kotlin,约定将以前命名的字段,属性以及方法进行颠覆。它们都以小驼峰(lowerCamelCase)的形式命名。
如果你开始使用Java,可以浏览来进行比较

工具

当你安装JDK时你可以得到一个编译器(javac)和一个jar创建器(jar),javadoc(用于创建Java文档)以及一些有用的工具。再加上一个文本编辑器你就可以创建并运行一个应用程序了。

关于IDE

Java领域中有三个主要的IDE:

这三个都是自由运营的。如果你想要有一些额外的框架支持,IntellIJ IDEA就有一个最终的商业运行版,换句话说,这有鲜明的企业特点。完整比较

虽然Eclipse可能是最常用的集成开发环境,但我还是选择用IntelliJ IDEA。如果你想用ReSharper,你一定会喜欢IntelliJ IDEA。当然,你可以说我偏袒它。

持续集成

在持续集成工具的方面,.NET和JVM有诸多相似之处。事实上,它们中的许多都是基于JVM的。

  • TeamCity – 提供一个免费版。
  • Jenkins – 是从Hudson中拆分出来的。

随机工具

我会将我发现有用的工具集加入进来。

  • JRebel – Awesome plugin to IntelliJ IDEA的一个相当棒的插件,其它IDE的代码可以支持热插拔,换句话说就是可以不经过编译就运行代码。
  • YourKit – Java分析器

站在Visual Studio用户角度看IntelliJ IDEA

这已经变为自己的指南

在JVM上工作

这部分描述了JVM上的常见情况。大多数例子是基于Kotlin的但是也可以比较容易地适应其它语言。

类加载器

JVM上的类加载器对于这篇指南而言过于庞大,所以我只想简单介绍一下。

在.NET中有一个集合类去加载其它类。在JVM上拥有类加载器。它不会是单个存在,换句话说,类加载器往往多于一个。

用于启动你的应用程序的默认类加载器可以通过使用类加载器中的方法getSystemClassLoader()

val classLoader = ClassLoader.getSystemClassLoader()


不要尝试去创建一个类加载器的实例,因为它是一个抽象类。有一些类加载器的实现经常使用,其中之一就是URL类加载器。

关于类加载器一个非常重要的观点是,每个类加载器有一个指向父类加载器的属性。

这是如何影响类加载器的呢?当你尝试加载一个类时,JVM首先将会尝试加载父类。如果父类不能加载这个类,那么你自己的类加载器就会进行加载。

类加载器,包括URL类加载器允许你在创建实例时指定一个可供选择的父类。

如果没有被子类没有将类加载成功,那么系统默认的类加载器会根据给定的classpath来进行加载操作。

同时,JVM中的类识别与.NET中很相似,那就意味着从不同的类加载器中加载相同的类将出现不兼容的情况,即使是在相同的链中也是如此。

创建你自己的类加载器

你不仅可以从ClassLoader类中创建你自己的类加载器,而且你也可以改变默认的类加载器,而这些在.NET几乎不可能。

关于类加载器的更多信息

关于类加载器的文章非常多。这里有一些我找到的:


仅使用Google就够了,因为通过它可以找到成千上万关于该主题的博客,文章和论文。

从当前动态类加载模块

在.NET中,想要加载从当前配置中加载一个类,你可以这样做:

var assembly = Assembly.GetExecutingAssembly(); 
var loadedClass = assembly.GetType("Loader.Customer");


加载器是当前用户所在命名空间的集合。这些工作的生命周期和当前集合的类一致。

在JVM中就是:

val classLoader = ClassLoader.getSystemClassLoader() 
val loadedClass = classLoader?.loadClass("org.loader.Customer")


这是Kotlin的用法,它表示,如果类加载器不为null,就执行这个操作。它是下面写法的简化版:

if (classLoader != null) {
        val loadedClass = classLoader.loadClass("org.loader.Customer")
}


从另一个模块中加载类

在.NET中,你会这么做:

var assembly = Assembly.LoadFrom(@"C:\Folder\SampleModule.dll"); 
var loadedClass = assembly.GetType("SampleModule.Customer");


在JVM上,你通常使用URL类加载器,将URL序列传递进去,而不是传递文件夹。 使用URL类加载器的好处就是你可以从磁盘和网络等地方加载。

如果你的类作为一个JAR打包,那么你可以这么定义JAR文件名:

val url = URL("file:///path-to-folder/sampleModule.jar") 
val urls = array(url) 
val classLoader = URLClassLoader.newInstance(urls) 
val loadedClass = classLoader?.loadClass("org.sampleModule.Customer")


你完全可以使用文件而不是URL,同时指向一个文件,这更加普遍,但之后你需要将文件转为URL:

val file = File("/path-to-folder/sampleModule.jar") 
val url = file.toURI().toURL()


如果你的类在文件夹中以单独的.class文件形式存在,你要指定文件夹名:

val url = URL("file:///path-to-root-folder/") 
val urls = array(url) 
val classLoader = URLClassLoader.newInstance(urls) 
val loadedClass = classLoader?.loadClass("org.sampleModule.Customer")


为什么我没有初始化URL类加载器,而使用newInstance方法?显然它的好处就是如果装有Security Manager的话就能调用securityManager.checkPackageAccess方法。

在使用目录时以下两点对于解决你的问题非常重要:(不是JAR文件):

确保你传递的URL或文件的后缀正确。
确保你在根文件夹下,那意味着什么呢?当你编译org.sampleModule.Customer这个类时,它产生了一个输出:output-root-folder/org/sampleModule/Customer.class
“.”替换成了“/”。这意味着URL加载器期望你指向根文件夹,而不是命名空间开始的地方。loadClass方法才需要提供完整的命名空间。

会议

近年来即使我不进行更多的Java开发,但是我一直在参加有关Java的会议。 这里有一些我参加会议后认为比较不错的建议和感受:

  • Devoxx – 最大的版本在安特卫普,但现在在法国和英国。
  • JAX – 德国的一个长期大型会议。一群水平相当的人的会议!
  • JavaZone – 这像是没有Java的开发者会。但是主要集中在挪威。
  • JavaOne – 颇具规模。它是Java领域的技术大会。
这里也有许多关于“跨平台”的会议NDCQConYOW!GOTO,等等。

本文由 ImportNew - Grey 翻译自 hadihariri
原文来自:http://www.importnew.com/10127.html
来自: ImportNew
3
0
评论 共 6 条 请登录后发表评论
6 楼 文仁126520 2014-03-19 16:27
讲java入门?你看的那本书了?我怎么不知道了?
5 楼 唔系好人 2014-03-17 08:55
  这翻译.......
4 楼 LinApex 2014-03-16 22:04
啥瞎扯淡,说的很详细,是讲java入门?早会了,谢谢
3 楼 hechuangqiang 2014-03-15 14:20
                             
2 楼 fjjiaboming 2014-03-15 08:09
    
1 楼 fjjiaboming 2014-03-15 08:09
var ??  java ....................

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • JVM最简生存指南

    为什么要写这个指南 持续更新目标人群 基础 Java语言,Java环境,Java虚拟机多语言平台JVM字节码跨平台 JVM部署和版本 版本 版本类型升级版本 Java的安装应用程序输出又叫Artifacts JAR文件WAR...

  • 可上手 JVM 调优实战指南

    JVM 调优快速上手指南。最快速度带你上手虚无神秘的 JVM 调优。

  • JVM常见面试题指南

    感兴趣的小伙伴们,可以关注我,或者通过搜索微信公众号:程序猿媛加油 了解更多知识点,还有有趣的生活类知识。 OK~话不多说,直接给内容吧: 基础题目 1.1 JDK、JRE、JVM的关系是什么? 什么是JVM? 英文名称...

  • JVM 常见面试题指南

    什么是 JVM? 什么是 JRE 什么是 JDK? 2. JVM 的内存模型以及分区情況和作用 如下图所示: 黄色部分为线程共有,蓝色部分为线程私有。方法区 堆 栈 本地方法栈 程序计数器 3. JVM对象创建步骤流程是什么? 整体流程...

  • JVM基础学习指南

    JVM面试指南

  • JVM 垃圾回收就是这么简单(转载)

    注意:我们在 可能是把Java内存区域讲的最清楚的一篇文章 也讲了JDK1.7及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。 2.6 如何判断一个类是无用...

  • JVM完全指南

    开发过程中,或程序运行过程中每次遇到OutOfMemory异常或GC异常或StackOverflowError异常我们都是一堆参数乱配,都把值调大,只是大体知道是跟jvm内存分配有关,具体应该怎么调,对应的异常应该调整那些参数,或者...

  • 搞定JVM垃圾回收就是这么简单

    上文回顾:《可能是把Java内存区域讲的最清楚的一篇文章》 写在前面 本节常见面试题: 问题答案在文中都有提到 如何判断对象是否死亡(两种方法)。 简单的介绍一下强引用、软引用、弱引用、虚引用(虚引用...

  • 八股文之jvm

    文章目录 jvm虚拟机 什么是jvm? jdk、jre、jvm是什么关系? jvm内存模型 堆内存申请对象空间流程 说一下 JVM 运行时数据区 说一下堆栈的区别? 队列和栈是什么?有什么区别? 对象创建方式 垃圾回收算法 标记-清除...

  • 搞定 JVM 垃圾回收就是这么简单

    JVM 的垃圾回收机制是Java 中比较重要的知识点,也是面试官常考的问题,本文主要围绕以下面试题来讲解JVM 的垃圾回收机制。 问题答案在文中都有提到 如何判断对象是否死亡(两种方法)。 简单的介绍一下强...

  • 【从基础到进阶实战】JVM 常见面试题指南助你横扫BAT!

    本文将重点介绍面试过程中常见的 JVM 题目。 将面试题分为三大类:基础题目,进阶题目,实战题目。基础1.1 JDK、 JRE、JVM 的关系是什么?什么是 JVM ?英文名称 ( Java Virtual Machine ),就是 JAVA 虚拟机, 它只...

  • 高性能服务器编程代码清单9-3,JRockit JVM优化清单/调优指南

    摘要本文的目的是以清单的方式提供BEA JRockit JVM的调优信息。从深奥的命令行选项到迭代性能测试,本文涵盖了许多方面。大部分数据都是我与用户合作过程中收集的。您要是也有什么技巧的话,请告诉我,在本文的下一...

  • 面渣逆袭:JVM经典五十问,这下面试稳了

    打算年后跳槽的,建议看看!不跳槽也可以先收藏。 五十问、六十一图、两万字,彻底搞定JVM!

  • JVM监测&工具

    前几篇篇文章介绍了介绍了JVM的参数设置并给出了一些生产环境的JVM参数配置参考方案。正如之前文章中提到的JVM参数的设置需要根据应用的特性来进行设置,每个参数的设置都需要对JVM进行长时间的监测,并不断进行调整...

  • 基于springboot大学生就业信息管理系统源码数据库文档.zip

    基于springboot大学生就业信息管理系统源码数据库文档.zip

  • 基于java的驾校收支管理可视化平台的开题报告.docx

    基于java的驾校收支管理可视化平台的开题报告

  • 原木5秒数据20241120.7z

    时间序列 原木 间隔5秒钟 20241120

  • 毕业设计&课设_基于 Vue 的电影在线预订与管理系统:后台 Java(SSM)代码,为毕业设计项目.zip

    毕业设计&课设_基于 Vue 的电影在线预订与管理系统:后台 Java(SSM)代码,为毕业设计项目.zip

  • 基于springboot课件通中小学教学课件共享平台源码数据库文档.zip

    基于springboot课件通中小学教学课件共享平台源码数据库文档.zip

  • 基于java的网上购物商城的开题报告.docx

    基于java的网上购物商城的开题报告

Global site tag (gtag.js) - Google Analytics