Category Archives: java

gperftool安装及使用说明

安装方法
1.从github上下载代码到服务器上
2../autogen.sh
需要提前安装autoconf,libtool,gcc-c++,libunwind。先安装libunwind,下载源码包:

./configure && make && make install
yum install -y autoconf libtool gcc-c++

使用方法

export LD_PRELOAD=/usr/lib/libtcmalloc.so:/usr/lib/libprofiler.so
CPUPROFILE=/tmp/cpu java ****
HEAPPROFILE=/tmp/heap java ****

查看结果:
pprof --text /bin/java /tmp/cpu
pprof --text /bin/java /tmp/heap

解决Jersey 2.x Jersey 1.x冲突问题– UriBuilder问题

最近在使用Java Docker来控制Docker的过程中发现了一个问题,因为Java Docker使用的是Jersey 2.x,maven pom如下:

<dependency>
    <groupId>com.github.docker-java</groupId>
    <artifactId>docker-java</artifactId>
    <version>3.0.13</version>
</dependency>

而集群中Hadoop的依赖都是Jersey 1.x。所以在引用的过程中提示如下错误:

Exception in thread "main" java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
        at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:119)
        at org.glassfish.jersey.client.JerseyWebTarget.<init>(JerseyWebTarget.java:71)
        at org.glassfish.jersey.client.JerseyClient.target(JerseyClient.java:290)
        at org.glassfish.jersey.client.JerseyClient.target(JerseyClient.java:76)
        at com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory.init(JerseyDockerCmdExecFactory.java:237)
        at com.github.dockerjava.core.DockerClientImpl.withDockerCmdExecFactory(DockerClientImpl.java:161)
        at com.github.dockerjava.core.DockerClientBuilder.build(DockerClientBuilder.java:45)

很明显这是Jersey版本mismatch导致的,在解决这一过程中,走了不少弯路,包括采用了maven shade plugin来解决,采用exclude一些jar包来解决等,都没有解决问题。
最后还是从错误出发,这个错误的原因是fromUri这个方法是一个抽象方法,没有实现,也就是只有抽象方法,没有实现类。
再把代码看一下,在Jersery 2.x中的实现为:

public abstract UriBuilder uri(String var1);

它的实现类为org.glassfish.jersey.uri.internal.JerseyUriBuilder,看到这一部分,大概了解到原因是缺少了实现类。于是加入相应的dependency到pom中

        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.23.1</version>
        </dependency>

加入后再打包,解决这一问题。

Java System.out重定向

近期在开发tensorflow-on-yarn的时候需要为启动的tensorflow添加环境变量,如获取所有的HADOOP CLASSPATH。在Hadoop命令行中,运行

Hadoop classpath --glob

即可获得所有的classpath,看了一下脚本,调用的是org.apache.hadoop.util.Classpath类,于是想到直接调用这个类就可以获得CLASSPATH了,但是发现直接调用输出到了stdout,所以就需要对System.out做重定向,获得需要的。
以下的代码就是重定向加上获得CLASSPATH

        // Get classpath
        PrintStream old_out = System.out;
        ByteArrayOutputStream pipeOut = new ByteArrayOutputStream();

        System.setOut(new PrintStream(new PrintStream(pipeOut)));
        Classpath.main(new String[]{"--glob"});
        System.setOut(old_out);
        String classpath = new String(pipeOut.toByteArray());
        env.put("CLASSPATH", System.getenv("CLASSPATH")+classpath);