float double NaN

float double NaN http://zranye.iteye.com/blog/1344880 http://blog.csdn.net/naruto_ahu/article/details/8805808 (注意,double中的NaN类似) 在帮助文档中,NaN是这样解释的 (double的,和float差不多) : public static final double NaN 保存 double 类型的 NaN 值的常量。它等于 Double.longBitsToDouble(0x7ff8000000000000L) 返回的值。 我是这样解释的 (理解不深,有错请不吝赐教) : NaN-Not-a-Number,其实是指一个不合理的实数,在合法却不合理的情况下避免你的程序出现Exception。 NaN什么也不是,如果理解成一个超越了float范围的常量 (或者double) ,那也是不对的,为什么?试试判断 (NaN==NaN) 吧,你会发现这返回了一个false。这在java底层是怎么做到的呢?最直接的方式是看java源代码咯。 /** A constant holding a Not-a-Number (NaN) value of type float. It is equivalent to the value returned by Float.intBitsToFloat(0x7fc00000). */ public static final float NaN = 0.0f / 0.0f; 上面这一段,就是floa的NaN定义了。这并不是一个超出了范围的常量,而是java的Float中人为得制造出来的一个合法但是不合理的实数了 (看来那位仁兄说得基本都对了) 。所以,NaN==NaN永远等于false啦。 那用什么来判断是否合理的Number呢?很奇怪的是,java提供了一个isNaN()的方法,指是否是一个不合理的实数。是否很拗口?我在javascript中第一次接触这个东西,也觉得很奇怪。 为什么有这样一个判断的方法不把NaN设置成private的,却又对外开放?难道担心我们不能主动制造一个不合理的实数出来?本人菜鸟,如果有高手能解答,还请不吝赐教,理解未深,有错误请指出,谢谢。 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;categories 改为 Java 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 4046-12-04 · Updated 9096-10-09 · 1 min · 83 words · -

netty http client

netty http client http://www.cnblogs.com/luxiaoxun/p/3959450.html 基于Netty4的HttpServer和HttpClient的简单实现 Netty的主页: http://netty.io/index.html 使用的Netty的版本: netty-4.0.23.Final.tar.bz2 ‐ 15-Aug-2014 (Stable, Recommended) Http 消息格式: Http request: Method path-to-resource HTTPVersion-number Header-name-1: value1 Header-name-2: value2 Optional request body Http response: HTTP/Version-number response-code response-phrase Header-name-1: value1 Header-name-2: value2 Optional response body 实现一个简单的Http请求及响应过程: Client向Server发送http请求。 Server端对http请求进行解析。 Server端向client发送http响应。 Client对http响应进行解析。 Netty中Http request消息格式: Netty中Http response消息格式: 代码实例: Http Server: package com.netty.test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; public class HttpServer { private static Log log = LogFactory.getLog(HttpServer.class); public void start(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码 ch.pipeline().addLast(new HttpResponseEncoder()); // server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码 ch.pipeline().addLast(new HttpRequestDecoder()); ch.pipeline().addLast(new HttpServerInboundHandler()); } }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HttpServer server = new HttpServer(); log.info("Http Server listening on 8844 ..."); server.start(8844); } } 响应请求的HttpServerInboundHandler: ...

Created 17176-12-17 · Updated 9096-10-09 · 2 min · 400 words · -

appassembler-maven-plugin

appassembler-maven-plugin Goals Overview [appassembler:assemble][1] Assembles the artifacts and generates bin scripts for the configured applications. [appassembler:create-repository][2] Creates an appassembler repository. [appassembler:generate-daemons][3] Generates JSW based daemon wrappers. maven 自动生成运行脚本插件appassembler-maven-plugin 博客分类: maven appassembler-maven-plugin可以自动生成跨平台的启动脚本,省去了手工写脚本的麻烦,而且还可以生成jsw的后台运行程序。 appassembler的配置比较简单,在pom.xml的配置文件加入插件配置。 比如说不同的启动脚本,可以如下配置 <plugin> <groupId>org.codehaus.mojo</groupId> appassembler-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <configurationDirectory>conf</configurationDirectory> <configurationSourceDirectory>src/main/resources</configurationSourceDirectory> <copyConfigurationDirectory>true</copyConfigurationDirectory> <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath> ${project.build.directory}/chj-search-client</assembleDirectory> <extraJvmArguments>-Xms128m</extraJvmArguments> <binFileExtensions> <unix>.sh</unix> </binFileExtensions> <platforms> <platform>windows</platform> <platform>unix</platform> </platforms> <repositoryName>lib</repositoryName> <programs> <program> <mainClass>com.chj360.search.client.App</mainClass> </program> </programs> </configuration> </plugin> 然后运行maven命令 :mvn package appassembler:assemble 就可以自动生成整个的依赖文件,配置文件和运行脚本了。 一些配置说明 configurationDirectory: 生成配置文件路径 configurationSourceDirectory: 配置文件原路径,默认为src/main/config assembleDirectory:整体包目录 ...

Created 5056-01-05 · Updated 9096-10-09 · 1 min · 184 words · -

maven profile

maven profile http://haohaoxuexi.iteye.com/blog/1900568 4 profile介绍 4.1 profile简介 profile可以让我们定义一系列的配置信息,然后指定其激活条件。这样我们就可以定义多个profile,然后每个profile对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果。比如说,我们可以通过profile定义在jdk1.5以上使用一套配置信息,在jdk1.5以下使用另外一套配置信息;或者有时候我们可以通过操作系统的不同来使用不同的配置信息,比如windows下是一套信息,linux下又是另外一套信息,等等。具体的激活条件有哪些我在后文会讲到。 4.2 profile的定义位置 对于使用Maven3,我们可以有多个地方定义profile。定义的地方不同,它的作用范围也不同。 (1) 针对于特定项目的profile配置我们可以定义在该项目的pom.xml中。 (2) 针对于特定用户的profile配置,我们可以在用户的settings.xml文件中定义profile。该文件在用户家目录下的".m2"目录下。 (3) 全局的profile配置。全局的profile是定义在Maven安装目录下的"conf/settings.xml"文件中的。 4.3 profile中能定义的信息 profile中能够定义的配置信息跟profile所处的位置是相关的。以下就分两种情况来讨论,一种是定义在settings.xml中,另一种是定义在pom.xml中。 4.3.1 profile定义在settings.xml中 当profile定义在settings.xml中时意味着该profile是全局的,它会对所有项目或者某一用户的所有项目都产生作用。因为它是全局的,所以在settings.xml中只能定义一些相对而言范围宽泛一点的配置信息,比如远程仓库等。而一些比较细致一点的需要根据项目的不同来定义的就需要定义在项目的pom.xml中。具体而言,能够定义在settings.xml中的信息有 <repositories>、<pluginRepositories>和<properties>。定义在<properties>里面的键值对可以在pom.xml中使用。 4.3.2 profile定义在pom.xml中 定义在pom.xml中的profile可以定义更多的信息。主要有以下这些: <repositories> <pluginRepositories> <dependencies> <plugins> <properties> <dependencyManagement> <distributionManagement> 还有build元素下面的子元素,主要包括: <defaultGoal> <resources> <testResources> <finalName> 4.4 profile的激活方式 Maven给我们提供了多种不同的profile激活方式。比如我们可以使用-P参数显示的激活一个profile,也可以根据环境条件的设置让它自动激活等。下面将对它们一一进行介绍: 4.4.1 使用activeByDefault设置激活 先看下面一个配置 <profiles> <profile> <id>profileTest1</id> <properties> <hello>world</hello> </properties> true</activeByDefault> </activation> </profile> <profile> <id>profileTest2</id> <properties> <hello>andy</hello> </properties> </profile> </profiles> 我们可以在profile中的activation元素中指定激活条件,当没有指定条件,然后指定activeByDefault为true的时候就表示当没有指定其他profile为激活状态时,该profile就默认会被激活。所以当我们调用mvn package的时候上面的profileTest1将会被激活,但是当我们使用mvn package –P profileTest2的时候将激活profileTest2,而这个时候profileTest1将不会被激活。 4.4.2 在settings.xml中使用activeProfiles指定处于激活状态的profile 我们可以在settings.xml中使用activeProfiles来指定需要激活的profile,这种方式激活的profile将所有情况下都处于激活状态。比如现在我们定义了如下两个profile <profiles> <profile> <id>profileTest1</id> <properties> <hello>world</hello> </properties> </profile> <profile> <id>profileTest2</id> <properties> <hello>andy</hello> </properties> </profile> </profiles> 这里的profile可以是定义在settings.xml中的,也可以是定义在pom.xml中的。这个时候如果我们需要指定profileTest1为激活状态,那么我们就可以在settings.xml中定义activeProfiles,具体定义如下: ...

Created 6066-01-06 · Updated 9096-10-09 · 2 min · 237 words · -

Maven 类包冲突的三个解决技巧, mvn dependency:tree

Maven类包冲突终极三大解决技巧 mvn dependency,tree http://ian.wang/106.htm Maven对于新手来说是《步步惊心》,因为它包罗万象,博大精深,因为当你初来乍到时,你就像一个进入森林的陌生访客一样迷茫。 Maven对于老手来说是《真爱配方》,因为它无所不能,利如刀锋,使用Maven做开发,如饮美酒如悦美人。 Maven对于新手来说,最痛苦的一件事莫过于包之间的冲突,由于Maven的依赖传递性,当你引入一个依赖类时,其身后的依赖类也一起如过江之鲫纷至沓来了。 举例 A依赖于B及C,而B又依赖于X、Y,而C依赖于X、M,则A除引B及C的依赖包下,还会引入X,Y,M的依赖包 (一般情况下了,Maven可通过<scope>等若干种方式控制传递依赖) 。 这里有一个需要特别注意的,即B和C同时依赖于X,假设B依赖于X的1.0版本,而C依赖于X的2.0版本,A究竟依赖于X的1.0还是2.0版本呢? 这就看Classloader的加载顺序了,假设Classloader先加载X_1.0,而它就不会再加载X_2.0了,如果A恰恰希望使用X_2.0呢,血案就这样不期而遇了。 三大技巧 第一板斧:找到传递依赖的鬼出在哪里? dependency:tree是把照妖照,pom.xml用它照照,所有传递性依赖都将无处遁形,并且会以层级树方式展现,非常直观。 以下就是执行dependency:tree后的一个输出: 引用 [INFO] - maven-dependency-plugin:2.1:tree (default-cli) @ euler-foundation - [INFO] com.hsit:euler-foundation:jar:0.9.0.1-SNAPSHOT [INFO] +- com.rop:rop:jar:1.0.1:compile [INFO] | +- org.slf4j:slf4j-api:jar:1.7.5:compile [INFO] | +- org.slf4j:slf4j-log4j12:jar:1.7.5:compile [INFO] | +- log4j:log4j:jar:1.2.16:compile [INFO] | +- commons-lang:commons-lang:jar:2.6:compile [INFO] | +- commons-codec:commons-codec:jar:1.6:compile [INFO] | +- javax.validation:validation-api:jar:1.0.0.GA:compile [INFO] | +- org.hibernate:hibernate-validator:jar:4.2.0.Final:compile [INFO] | +- org.codehaus.jackson:jackson-core-asl:jar:1.9.5:compile [INFO] | +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.5:compile [INFO] | +- org.codehaus.jackson:jackson-jaxrs:jar:1.9.5:compile [INFO] | +- org.codehaus.jackson:jackson-xc:jar:1.9.5:compile ...

Created 17176-02-17 · Updated 9096-10-09 · 2 min · 375 words · -

Java Unix Socket 2

java unix socket <dependency> <groupId>uk.co.caprica</groupId> juds</artifactId> <version>0.94.1</version> </dependency> 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;文件重命名为 unix-socket-2.md;title 改为「Java Unix Socket 2」;categories 改为 Java 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 29296-02-29 · Updated 9096-10-09 · 1 min · 31 words · -

Netty HTTP 文件服务器

netty http文件服务器 http://krisjin.github.io/2015/02/14/netty-file-server/ Http介绍 Http(超文本传输协议)协议是建立在TCP传输协议之上的应用成协议,Http由于便捷、快速的方式,适用于分布式超媒体信息系统。Http是目前Web开发的主流协议,基于Http的应用非常广泛,因此掌握HTTP的开发非常重要。由于netty的HTTP协议栈是基于netty的NIO通信框架开发的,所以netty的HTTP协议也是异步非阻塞的。 具体的关于HTTP及Netyy的实现细节在以后的章节在写,先上实例代码: 实例代码 服务端: public class HttpFileServer { public void run(final int port, final String url) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap boot = new ServerBootstrap(); boot.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("http-decoder", new HttpRequestDecoder()); ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536)); ch.pipeline().addLast("http-encoder", new HttpResponseEncoder()); ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); ch.pipeline().addLast("fileServerHandler", new HttpFileServerHandler(url)); } }); ChannelFuture cf =boot.bind("127.0.0.1",port).sync(); System.out.println("Http文件目录服务器启动: [http://127.0.0.1](http://127.0.0.1):"+port+url); cf.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { String url="/src/main/java/"; new HttpFileServer().run(8080, url); } } 服务端handler ...

Created 20206-03-20 · Updated 9096-10-09 · 3 min · 631 words · -

Java 数组合并

java 数组 合并 http://blog.csdn.net/jaycee110905/article/details/9179227 Java中如何把两个数组合并为一个 标签: JavaArray合并数组 2013-06-26 14:54 22185人阅读 评论(1) 收藏 举报 分类: JAVA (39) 目录(?)[+] http://freewind.me/blog/20110922/350.html 在Java中,如何把两个String[]合并为一个? 看起来是一个很简单的问题。但是如何才能把代码写得高效简洁,却还是值得思考的。这里介绍四种方法,请参考选用。 一、apache-commons 这是最简单的办法。在apache-commons中,有一个ArrayUtils.addAll(Object[], Object[])方法,可以让我们一行搞定: String[] both = (String[]) ArrayUtils.addAll(first, second); 其它的都需要自己调用jdk中提供的方法,包装一下。 为了方便,我将定义一个工具方法concat,可以把两个数组合并在一起: static String[] concat(String[] first, String[] second) {} 为了通用,在可能的情况下,我将使用泛型来定义,这样不仅String[]可以使用,其它类型的数组也可以使用: static <T> T[] concat(T[] first, T[] second) {} 当然如果你的jdk不支持泛型,或者用不上,你可以手动把T换成String。 二、System.arraycopy() static String[] concat(String[] a, String[] b) { String[] c= new String[a.length+b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); return c; } 使用如下: ...

Created 25256-03-25 · Updated 9096-10-09 · 2 min · 255 words · -

DbUnit

DbUnit http://yangzb.iteye.com/blog/947292 博客分类: QC 单元测试XML数据结构OraclePostgreSQL 相信做过单元测试的人都会对JUnit 非常的熟悉了,今天要介绍的DbUnit(http://dbunit.sourceforge.net/ ) 则是专门针对数据库测试的对JUnit 的一个扩展,它可以将测试对象数据库置于一个测试轮回之间的状态。鉴于目前国内介绍DbUnit 的系统教程比较少见,本文将分从理论和实例两个方面带你领略DbUnit 的精彩世界。 DbUnit 设计理念 熟悉单元测试的开发人员都知道,在对数据库进行单元测试时候,通常采用的方案有运用模拟对象(mock objects)和stubs 两种。通过隔离关联的数据库访问类,比如JDBC 的相关操作类,来达到对数据库操作的模拟测试。然而某些特殊的系统,比如利用了EJB 的CMP(container-managed persistence) 的系统,数据库的访问对象是在最底层而且很隐蔽的,那么这两种解决方案对这些系统就显得力不从心了。 DBUnit 的设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,最后,在测试完毕后,读入备份数据库,回溯到测试前的状态; 而且又因为DBUnit 是对JUnit 的一种扩展,开发人员可以通过创建测试用例代码,在这些测试用例的生命周期内来对数据库的操作结果进行比较。 DbUnit 测试基本概念和流程 基于DbUnit 的测试的主要接口是IDataSet 。IDataSet 代表一个或多个表的数据。 可以将数据库模式的全部内容表示为单个IDataSet 实例。这些表本身由Itable 实例来表示。 IDataSet 的实现有很多,每一个都对应一个不同的数据源或加载机制。最常用的几种 IDataSet 实现为: FlatXmlDataSet : 数据的简单平面文件 XML 表示 QueryDataSet : 用 SQL 查询获得的数据 DatabaseDataSet : 数据库表本身内容的一种表示 XlsDataSet : 数据的excel 表示 一般而言,使用DbUnit 进行单元测试的流程如下: 1 根据业务,做好测试用的准备数据和预想结果数据,通常准备成xml 格式文件。 2 在setUp() 方法里边备份数据库中的关联表。 3 在setUp() 方法里边读入准备数据。 4 对测试类的对应测试方法进行实装: 执行对象方法,把数据库的实际执行结果和预想结果进行比较。 ...

Created 13136-04-13 · Updated 9096-10-09 · 3 min · 517 words · -

Netty File Upload 文件上传

netty 文件上传 http://blog.csdn.net/mcpang/article/details/41140409 【初学与研发之NETTY】netty4之文件上传 标签: netty4文件上传 2014-11-15 04:35 6005人阅读 评论(29) 收藏 举报 分类: JAVA (48) Netty (6) 版权声明: 本文为博主原创文章,未经博主允许不得转载。 客户端: public class UpLoadClient { private StringBuffer resultBuffer = new StringBuffer(); private EventLoopGroup group = null; private HttpDataFactory factory = null; private Object waitObject = new Object(); private ChannelFuture future = null; public UpLoadClient(String host, int port) throws Exception { this.group = new NioEventLoopGroup(); this.factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); Bootstrap b = new Bootstrap(); b.option(ChannelOption.TCP_NODELAY, true); b.option(ChannelOption.SO_SNDBUF, 1048576*200); b.option(ChannelOption.SO_KEEPALIVE, true); b.group(group).channel(NioSocketChannel.class); b.handler(new UpLoadClientIntializer()); this.future = b.connect(host, port).sync(); } public void uploadFile(String path) { if(path == null) { System.out.println("上传文件的路径不能为null..."); return; } File file = new File(path); if (!file.canRead()) { System.out.println(file.getName() + "不可读..."); return; } if (file.isHidden() || !file.isFile()) { System.out.println(file.getName() + "不存在..."); return; } try { HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, ""); HttpPostRequestEncoder bodyRequestEncoder = new HttpPostRequestEncoder(factory, request, false); bodyRequestEncoder.addBodyAttribute("getform", "POST"); bodyRequestEncoder.addBodyFileUpload("myfile", file, "application/x-zip-compressed", false); List<InterfaceHttpData> bodylist = bodyRequestEncoder.getBodyListAttributes(); if (bodylist == null) { System.out.println("请求体不存在..."); return; } HttpRequest request2 = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, file.getName()); HttpPostRequestEncoder bodyRequestEncoder2 = new HttpPostRequestEncoder(factory, request2, true); bodyRequestEncoder2.setBodyHttpDatas(bodylist); bodyRequestEncoder2.finalizeRequest(); Channel channel = this.future.channel(); if(channel.isActive() && channel.isWritable()) { channel.writeAndFlush(request2); if (bodyRequestEncoder2.isChunked()) { channel.writeAndFlush(bodyRequestEncoder2).awaitUninterruptibly(); } bodyRequestEncoder2.cleanFiles(); } channel.closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } } public void shutdownClient() { // 等待数据的传输通道关闭 group.shutdownGracefully(); factory.cleanAllHttpDatas(); } public boolean isCompleted() { while(waitObject != null) { //当通道处于开通和活动时,处于等待 } if(resultBuffer.length() > 0) { if("200".equals(resultBuffer.toString())) { resultBuffer.setLength(0); return true; } } return false; } private class UpLoadClientIntializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder", new HttpResponseDecoder()); pipeline.addLast("encoder", new HttpRequestEncoder()); pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); pipeline.addLast("dispatcher", new UpLoadClientHandler()); } } private class UpLoadClientHandler extends SimpleChannelInboundHandler<HttpObject> { private boolean readingChunks = false; private int succCode = 200; protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; succCode = response.getStatus().code(); if (succCode == 200 && HttpHeaders.isTransferEncodingChunked(response)) { readingChunks = true; } } if (msg instanceof HttpContent) { HttpContent chunk = (HttpContent) msg; System.out.println("【响应】"+succCode+">>"+chunk.content().toString(CharsetUtil.UTF_8)); if (chunk instanceof LastHttpContent) { readingChunks = false; } } if (!readingChunks) { resultBuffer.append(succCode); ctx.channel().close(); } } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { waitObject = null; } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { resultBuffer.setLength(0); resultBuffer.append(500); System.out.println("管道异常: " + cause.getMessage()); cause.printStackTrace(); ctx.channel().close(); } } } 服务端: ...

Created 24246-05-24 · Updated 9096-10-09 · 6 min · 1159 words · -

Maven Dependency Inheritance 依赖与继承

maven 依赖 继承 Project A 被 Project B 调用 比如 A 里有 mockito的jar包, B要引用A , 从而不需要在B里直接引用mockito的jar包,而且A 包里的自建代码也可以用起来。 关键点在于 A 的pom里不能 用 test scope来藏起来A里面的jar ,这样B就无法继承到了。 Maven依赖范围及依赖传递 一: 依赖范围scope 共5种,compile (编译)、test (测试)、runtime (运行时)、provided、system 不指定,则依赖范围默认为compile. compile:编译依赖范围,在编译,测试,运行时都需要。 test: 测试依赖范围,测试时需要。编译和运行不需要。如Junit runtime: 运行时依赖范围,测试和运行时需要。编译不需要。如JDBC驱动包 provided:已提供依赖范围,编译和测试时需要。运行时不需要。如servlet-api system:系统依赖范围。本地依赖,不在maven中央仓库。 二: 依赖的传递 A->B(compile) 第一关系: a依赖b compile B->C(compile) 第二关系: b依赖c compile 当在A中配置 <dependency> <groupId>com.B</groupId> B</artifactId> <version>1.0</version> </dependency> 则会自动导入c包。关系传递如下表: 第一 第二 compile test provided runtime compile compile runtime test test test ...

Created 5056-07-05 · Updated 9096-10-09 · 1 min · 145 words · -

PreparedStatementCache

PreparedStatementCache http://www.cnblogs.com/alipayhutu/archive/2013/04/18/3029171.html 如何理解PreparedStatementCache,以及如何使用 为节约键盘敲击次数,记PreparedStatement为PS, PreparedStatementCache为PSCache,并且所有的SQL使用的绑定变量。 原理: http://www.dbafree.net/?p=287 http://agapple.iteye.com/blog/838286 http://singleant.iteye.com/blog/1298837 使用: 使用ps. sql里用?占位,等待被替换。例如,select * from table1 where user_name = ? and age > ? 启用pscache。 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> .... <property name="poolPreparedStatements" value="true" /> <property name="maxOpenPreparedStatements" value="10" /> .... </bean> 解析后的PS缓存,与重复利用。 sql语句,被发送到DB server端,经一系列处理 (语法解析、语义解析、结构优化) ,转化为一个树型结构 (sql, string -> tree) 。 3.1 sql解析后 (string -> tree) ,如何将ps放到pscache里? 首先,澄清个概念。执行树这个不是在应用客户端的,是在oracle服务器那边,server中也有pscache. 再者是说,只要客户端开启了PSCache,那么CS端都会缓存住这些个树 (尽管C端维护的结构可能简单一点) 。 底层会缓存 (LRU替换) ,用户不用关心。 3.2 假如pscache中,有一棵树是select * from table1 where user_name = ? and age > ? ,现在并发来了50个线程,都要用这棵树,如何复用? 执行树是一个具体的执行步骤了,是oracle服务器底层的具体执行步骤,所以再多的并发,直接拿过来用就是了,跟并发没有很多的关系。 可以理解为一个非状态的公共方法,就可以了,多个线程直接调用,复用这个方法,不存在瓶颈。 本质上来说,是oracle底层"包揽了"。底层逻辑: 根据sql (String及参数类型等各种信息) ,计算出一个key,看它在pscache里是否存在。 ...

Created 22226-09-22 · Updated 9096-10-09 · 1 min · 103 words · -

gradle maven snapshot

gradle maven snapshot configurations.all { // check for updates every build resolutionStrategy.cacheChangingModulesFor 0, ‘seconds’ } dependencies { compile group: “group”, name: “projectA”, version: “1.1-SNAPSHOT”, changing: true } https://discuss.gradle.org/t/how-to-get-gradle-to-download-newer-snapshots-to-gradle-cache-when-using-an-ivy-repository/7344 gradle maven plugin https://docs.gradle.org/current/userguide/publishing_maven.html#header gradle v5.3.1 group = "com.wiloon.group0" version = "0.0.1-SNAPSHOT" plugins { `java-library` `maven-publish` id("com.gradle.build-scan") version "2.2.1" } tasks.register<Jar>("sourcesJar") { from(sourceSets.main.get().allJava) archiveClassifier.set("sources") } tasks.register<Jar>("javadocJar") { from(tasks.javadoc) archiveClassifier.set("javadoc") } publishing { publications { create<MavenPublication>("maven") { from(components["java"]) artifact(tasks["sourcesJar"]) artifact(tasks["javadocJar"]) } } repositories { maven { val releasesRepoUrl = "http://nexus.wiloon.com/repository/maven-releases" val snapshotsRepoUrl = "http://nexus.wiloon.com/repository/maven-snapshots" url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl) credentials { username = "admin" password = "password" } } } } 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码;categories 改为 Java 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 6066-11-06 · Updated 9096-10-09 · 1 min · 118 words · -

NMT, Native Memory Tracking

NMT, Native Memory Tracking NMT for Hotspot VM is turned off by default. Turn this feature on using JVM command line option -XX:NativeMemoryTracking=[off | summary | detail] 注意,根据Java官方文档,开启NMT会有5%-10%的性能损耗; 访问NMT数据 JDK提供了jcmd命令来访问NMT数据: jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB] 配置项 说明 summary 只打印打印按分类汇总的内存 detail 打印按分类汇总的内存用法、virtual memory map和每次内存分配调用 baseline 创建内存快照,以比较不同时间的内存差异 summary.diff 打印自上次baseline到现在的内存差异,显示汇总信息 detail.diff 打印自上次baseline到现在的内存差异, 显示详细信息 shutdown 关闭NMT功能,NMT can be shutdown using jcmd utility, but can not start/restart using jcmd ...

Created 6066-02-06 · Updated 9096-10-09 · 1 min · 110 words · -

Retained Heap

Retained Heap http://supercharles888.blog.51cto.com/609344/1347144 为了开始研究,我们希望在memory 溢出时候能自动生成heap dump文件,为此,我们在运行时候添加JVM 参数: -XX:+HeapDumpOnOutOfMemoryError 然后,我们来做一系列实验来逐步研究各个有趣的问题。 实验1: 我们先来研究最简单的memory leak例子。我们先构造一个POJO类Person,这个Person类就是一般的java 类,然后我们构造一个ArrayList,然后在一个无限循环中一直放这个Person类的实例,因为Person类和ArrayList都在堆上,而ArrayList因为是强引用,所以无法被GC回收, (因为我们List一直在用并没有摧毁) 所以一旦ArrayList所占用的堆内存填满整个heap size时候,heap就溢出了。 POJO类代码是: package com.charles.research; /** * * 这是一个Person类,我用它来撑满heap * @author charles.wang * */ public class Person { private String name; private String sex; private int age; public Person( String name,String sex,int age){ this.name=name; this.sex=sex; this.age=age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 然后我们创建ArrayList,并且无限向其中添加Person类对象的方法是: ...

Created 7076-02-07 · Updated 9096-10-09 · 2 min · 416 words · -

ThreadLocal

ThreadLocal ThreadLocal 是什么 弱引用 避免内存溢出的操作 开放地址法解决 hash 冲突 各种内部类 线程本地变量有时会简写为 TLV, Thread Local Variables ThreadLocal 是什么 ThreadLocal 是线程的局部变量, 也就是说这个变量是线程独有的。 通常情况下, 我们创建的变量是可以被任何一个线程访问并修改的。而使用 ThreadLocal 创建的变量只能被当前线程访问, 其他线程则无法访问和修改。 变量是同一个, 但是每个线程都使用同一个初始值, 也就是使用同一个变量的一个新的副本, 这种情况下 TreadLocal 就非常有用。 应用场景: 当很多线程需要多次使用同一个对象, 并且需要该对象具有相同初始值的时候, 最适合使用TreadLocal。 事实上,从本质上讲,就是每个线程都维持一个 MAP,而这个map的key就是TreadLocal,而值就是我们set的那个值,每次线程在get的时候,都从自己的变量中取值,既然从自己的变量中取值,那就肯定不存在线程安全的问题。总体来讲,TreadLocal这个变量的状态根本没有发生变化。它仅仅是充当了一个key的角色,另外提供给每一个线程一个初始值。如果允许的话,我们自己就能实现一个这样的功能,只不过恰好JDK就已经帮助我们做了这个事情。 使用TreadLocal维护变量时, TreadLocal为每个使用该变量的线程提供独立地变量副本, 所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。从线程的角度看,目标变量对象是线程的本地变量,这也是类名中Local所需要表达的意思。 TreadLocal的四个方法 void set(Object val),设置当前线程的线程局部变量的值 Object get () 返回当前线程所对用的线程局部变量。 void remove() 将当前线程局部变量的值删除,目的是为了减少内存的占用,线程结束后,局部变量自动被GC Object initValue() 返回该线程局部变量的初始值,使用protected修饰,显然是为了让子类覆盖而设计的。 ThreadLocalMap HashMap 的数据结构是数组+链表 ThreadLocalMap的数据结构仅仅是数组 HashMap 是通过链地址法解决 hash 冲突的问题 ThreadLocalMap 是通过开放地址法来解决 hash 冲突的问题 HashMap 里面的Entry 内部类的引用都是强引用 ThreadLocalMap里面的Entry 内部类中的key 是弱引用,value 是强引用 对象存放在哪里 在Java中, 栈内存归属于单个线程, 每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。 ...

Created 24246-03-24 · Updated 9096-10-09 · 3 min · 619 words · -

Guava cache

Guava cache http://www.cnblogs.com/peida/p/Guava_Cache.html 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用。在日常开发的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们发现我们的系统这个数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现。缓存的作用就是将这些来自不易的数据保存在内存中,当有其他线程或者客户端需要查询相同的数据资源时,直接从缓存的内存块中返回数据,这样不但可以提高系统的响应时间,同时也可以节省对这些数据的处理流程的资源消耗,整体上来说,系统性能会有大大的提升。 缓存在很多系统和架构中都用广泛的应用,例如: 1.CPU缓存 2.操作系统缓存 3.本地缓存 4.分布式缓存 5.HTTP缓存 6.数据库缓存 等等,可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。 Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好。 Guava Cache有两种创建方式: cacheLoader callable callback 通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定。 cacheLoader方式实现实例: @Test public void TestLoadingCache() throws Exception{ LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() .build(new CacheLoader<String, String>(){ @Override public String load(String key) throws Exception { String strProValue="hello "+key+"!"; return strProValue; } }); System.out.println("jerry value:"+cahceBuilder.apply("jerry")); System.out.println("jerry value:"+cahceBuilder.get("jerry")); System.out.println("peida value:"+cahceBuilder.get("peida")); System.out.println("peida value:"+cahceBuilder.apply("peida")); System.out.println("lisa value:"+cahceBuilder.apply("lisa")); cahceBuilder.put("harry", "ssdded"); System.out.println("harry value:"+cahceBuilder.get("harry")); } 输出: ...

Created 31316-03-31 · Updated 9096-10-09 · 3 min · 496 words · -

Java jps

java jps jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号。 jps相当于Solaris进程工具ps。不象"pgrep java"或"ps -ef grep java",jps并不使用应用程序名来查找JVM实例。因此,它查找所有的Java应用程序,包括即使没有使用java执行体的那种 (例如,定制的启动 器) 。另外,jps仅查找当前用户的Java进程,而不是当前系统中的所有进程。 -h: help -l: 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名 -m: 输出传递给main 方法的参数,在嵌入式jvm上可能是null, 在这里,在启动main方法的时候,我给String[] args传递两个参数。hollis,chuang,执行jsp -m: -v: 输出传递给JVM的参数 在这里,在启动main方法的时候,我给jvm传递一个参数: -Dfile.encoding=UTF-8,执行jps -v: 位置 我们知道,很多Java命令都在jdk的JAVA_HOME/bin/目录下面,jps也不例外,他就在bin目录下,所以,他是java自带的一个命令。 功能 jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。 原理 jdk中的jps命令可以显示当前运行的java进程以及相关参数,它的实现机制如下: java程序在启动以后,会在java.io.tmpdir指定的目录下,就是临时文件夹里,生成一个类似于hsperfdata_User的文件夹,这个文件夹里 (在Linux中为/tmp/hsperfdata_{userName}/) ,有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已。 至于系统的参数什么,就可以解析这几个文件获得。 hollis@hos:/tmp/hsperfdata_hollis$ pwd /tmp/hsperfdata_hollis hollis@hos:/tmp/hsperfdata_hollis$ ll total 48 drwxr-xr-x 2 hollis hollis 4096 4月 16 10:54 ./ drwxrwxrwt 7 root root 12288 4月 16 10:56 ../ ...

Created 5056-05-05 · Updated 9096-10-09 · 2 min · 243 words · -

On-Heap and Off-Heap Memory 堆内内存, 堆外内存

堆内内存, 堆外内存 一、什么是堆外内存 堆内内存 (on-heap memory) 回顾 堆外内存和堆内内存是相对的二个概念,其中堆内内存是我们平常工作中接触比较多的,我们在jvm参数中只要使用-Xms,-Xmx等参数就可以设置堆的大小和最大值,理解jvm的堆还需要知道下面这个公式: 堆内内存 = 新生代+老年代+持久代 如下面的图所示: Paste_Image.png 在使用堆内内存 (on-heap memory) 的时候,完全遵守JVM虚拟机的内存管理机制,采用垃圾回收器 (GC) 统一进行内存管理,GC会在某些特定的时间点进行一次彻底回收,也就是Full GC,GC会对所有分配的堆内内存进行扫描,在这个过程中会对JAVA应用程序的性能造成一定影响,还可能会产生Stop The World。 常见的垃圾回收算法主要有: 引用计数器法 (Reference Counting) 标记清除法 (Mark-Sweep) 复制算法 (Coping) 标记压缩法 (Mark-Compact) 分代算法 (Generational Collecting) 分区算法 (Region) 注: 在这里我们不对各个算法进行深入介绍,感兴趣的同学可以关注我的下一篇关于垃圾回收算法的介绍分享。 堆外内存 (off-heap memory) 介绍 和堆内内存相对应,堆外内存就是把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理 (而不是虚拟机) ,这样做的结果就是能够在一定程度上减少垃圾回收对应用程序造成的影响。 作为JAVA开发者我们经常用java.nio.DirectByteBuffer对象进行堆外内存的管理和使用,它会在对象创建的时候就分配堆外内存。 DirectByteBuffer类是在Java Heap外分配内存,对堆外内存的申请主要是通过成员变量unsafe来操作,下面介绍构造方法 DirectByteBuffer(int cap) { super(-1, 0, cap, cap); //内存是否按页分配对齐 boolean pa = VM.isDirectMemoryPageAligned(); //获取每页内存大小 int ps = Bits.pageSize(); //分配内存的大小,如果是按页对齐方式,需要再加一页内存的容量 long size = Math.max(1L, (long)cap + (pa ? ps : 0)); //用Bits类保存总分配内存(按页分配)的大小和实际内存的大小 Bits.reserveMemory(size, cap); long base = 0; try { //在堆外内存的基地址,指定内存大小 base = unsafe.allocateMemory(size); } catch (OutOfMemoryError x) { Bits.unreserveMemory(size, cap); throw x; } unsafe.setMemory(base, size, (byte) 0); //计算堆外内存的基地址 if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); } else { address = base; } cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); att = null; } 注: 在Cleaner 内部中通过一个列表,维护了一个针对每一个 directBuffer 的一个回收堆外内存的 线程对象(Runnable),回收操作是发生在 Cleaner 的 clean() 方法中。 ...

Created 17176-05-17 · Updated 9096-10-09 · 3 min · 500 words · -

ForkJoin

ForkJoin ForkJoinPool 适合执行计算密集型且可进行拆分任务并汇总结果(类似MapReduce)的任务,执行这种任务可以充分利用多核处理器优势提高任务处理速度,实际上 ForkJoinPool 内部的工作窃取队列的高性能 (远高于普通线程池的BlockingQueue) 也决定其适用于执行大量的简短的小任务。 ———————————————— 版权声明:本文为CSDN博主「heng_zou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/heng_zou/article/details/118193846 什么是 Fork/Join 框架 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架(Fork/Join Framework), 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。 我们再通过 Fork 和 Join 这两个单词来理解下 Fork/Join 框架,Fork 就是把一个大任务切分为若干子任务并行的执行,Join 就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算 1+ 2+… + 10000,可以分割成 10 个子任务,每个子任务分别对 1000 个数进行求和,最终汇总这 10 个子任务的结果。 ForkJoinPool http://blog.dyngr.com/blog/2016/09/15/java-forkjoinpool-internals/ ForkJoinPool 不是为了替代 ExecutorService, 而是它的补充, 在某些应用场景下性能比 ExecutorService 更好。 (见 Java Tip: When to use ForkJoinPool vs ExecutorService ) https://www.infoworld.com/article/2078440/java-tip-when-to-use-forkjoinpool-vs-executorservice.html ForkJoinPool 主要用于实现"分而治之"的算法, 特别是分治之后递归调用的函数, 例如 quick sort 等。 [[quick-sort]] ForkJoinPool 最适合的是计算密集型的任务, 如果存在 I/O, 线程间同步, sleep() 等会造成线程长时间阻塞的情况时, 最好配合使用 ManagedBlocker ...

Created 22226-06-22 · Updated 9096-10-09 · 4 min · 744 words · -