- 浏览: 107851 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (99)
- 经济 (1)
- dwr (2)
- 测试 (0)
- java (29)
- resin (1)
- oracle (3)
- 感悟 (1)
- jvm (15)
- mina2 (5)
- j2se (12)
- linux (28)
- protobuf (1)
- tcp/ip (0)
- jdbc (0)
- 数据库 (4)
- 游戏 (0)
- 技术文档 (1)
- nosql (2)
- 算法 (2)
- apache (2)
- mysql (1)
- hashcode (1)
- spring (2)
- quartz (5)
- netcat (2)
- 分页 (1)
- 正则 (0)
- shell (1)
- lsof (1)
- nginx (1)
- git (1)
最新评论
-
fys124974704:
你试下将第三条写成以下这样,你会发现你的结论不对:select ...
ORACLE分页SQL语句 -
ikon:
两个乘数没有转成integer,而是当成字符串;BigInte ...
计算任意2个正整数的乘积 -
kidding87:
效率不是很高,思路没有问题,但是你的两个乘数输入都都转为Int ...
计算任意2个正整数的乘积 -
k1280000:
------------------------同意!
学习之道
前些天使用Java调用外部程序的时候,发现线程会堵塞在waitfor()方法。 如果直接在Shell中调用这个程序,程序会很快结束,不会僵死。 为什么会堵塞呢,原因是当调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立3个管道连接,标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取,数据会暂时缓冲在Linux的缓冲区,缓冲区满后该程序将无法继续写数据,会僵死,所以Java程序就会僵死在waitfor(),永远无法结束。 解决办法就是增加两个线程,一个线程负责读标准输出流,另一个负责读标准错误流,这样子数据就不会积压在缓冲区,程序就能够顺利运行。 查看源代码后,还发现一个潜在的问题。但程序执行到exec的时候,JVM会使用管道,占有3个文件句柄,但程序运行结束后,这三个句柄并不会自动关闭,这样最终会导致java.io.IOException: Too many open files。所以就算外部程序的没有输出,也必须关闭句柄: 我们发觉当调用close()方法后,JVM并不会立即回收句柄,具体的回收时间不确定。另外如果不调用close(),句柄也会被回收,也可能发生“Too many open files”的错误。根据这篇文章,不同的垃圾收集器会选择不同的回收策略。所以最好还是要关闭。 总结
调用方法如下:
1.如果外部程序有大量输出,需要启动额外的线程来读取标准输出和标准错误流
2.必须关闭三个句柄
import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ProcessUtil { private static final int DEFAULT_BUFFER_SIZE = 1024; private static Log log = LogFactory.getLog(ProcessUtil.class); private InputStream in; private OutputStream out; private OutputStream err; public ProcessUtil(OutputStream out, OutputStream err, InputStream in) { if (out == null) { out = new NullOutputStream(); } if (err == null) { err = new NullOutputStream(); } this.out = out; this.err = err; this.in = in; } public int process(String cmd, String[] envp, File dir) throws IOException, InterruptedException { Process p = Runtime.getRuntime().exec(cmd, envp, dir); return process(p); } public int process(String[] cmdarray, String[] envp, File dir) throws IOException, InterruptedException { Process p = Runtime.getRuntime().exec(cmdarray, envp, dir); return process(p); } private int process(Process p) throws IOException, InterruptedException { try { OutputStream pin = p.getOutputStream(); StreamGobbler outg = new StreamGobbler(p.getInputStream(), out); StreamGobbler errg = new StreamGobbler(p.getErrorStream(), err); outg.start(); errg.start(); if (in != null) { byte[] inBuf = new byte[DEFAULT_BUFFER_SIZE]; int inN = 0; while (-1 != (inN = in.read(inBuf))) { pin.write(inBuf, 0, inN); } pin.flush(); } int code = p.waitFor(); outg.join(); errg.join(); return code; } finally { closeQuietly(p.getOutputStream()); closeQuietly(p.getInputStream()); closeQuietly(p.getErrorStream()); } } private void closeQuietly(Closeable closeable) { try { if (closeable != null) closeable.close(); } catch (Exception e) { log.warn("close error", e); } } } class StreamGobbler implements Runnable { private static final int DEFAULT_BUFFER_SIZE = 1024; private static Log log = LogFactory.getLog(StreamGobbler.class); private InputStream is; private OutputStream os; private Thread thread; public StreamGobbler(InputStream is, OutputStream os) { this.is = is; this.os = os; } public void start() { thread = new Thread(this); thread.setDaemon(true); thread.start(); } public void run() { try { byte[] buf = new byte[DEFAULT_BUFFER_SIZE]; int n = 0; while (-1 != (n = is.read(buf))) { os.write(buf, 0, n); } os.flush(); } catch (Exception ex) { log.warn("stream error", ex); } } public void join() throws InterruptedException { thread.join(); } } class NullOutputStream extends OutputStream { public static final NullOutputStream NULL_OUTPUT_STREAM = new NullOutputStream(); @Override public void write(byte[] b, int off, int len) { } @Override public void write(int b) { } @Override public void write(byte[] b) throws IOException { } }
发表评论
-
获取堆栈转储信息
2012-09-12 10:21 0咨询个关于获得java进程堆栈信息的问题 ... -
ulimit 放开用户限制 生成core文件
2012-09-12 10:04 1449ulimit -a 用来显示当前的各种用户进程限制。 ... -
coredump使用方法
2012-09-12 10:02 1559Linux系统下程序出错时会自动生成一个core文件,该 ... -
一个java crash的故障分析过程
2012-09-12 09:55 871一个应用在周五出现java进程消失,没有任何日志。先查看 ... -
Linux 系统设置 ulimit 以及 Core文件的生成
2012-09-12 09:55 1179查看限制情况 ulimit -a 可以看到如下信息 ... -
线上游戏的gc情况
2012-07-18 15:47 902resin jvm参数配置如下: ... -
JVM调优的几种策略(好)
2012-07-18 14:59 878JVM参数调优是一个很 ... -
Java GC 日志详解
2012-07-18 14:51 820ava GC日志可以通过 +PrintGCDetails ... -
JVM GC日志时间问题
2012-07-18 14:22 1086几乎所有的资料上说到打印JVM GC log的时候都会 ... -
jstat应用
2012-06-27 17:33 779用以判断JVM是否存在内存问题呢?如何判断JVM垃圾回收 ... -
Quartz定时任务学习(一)简单任务
2012-04-27 12:30 893学习quartz首先了解三个概念: 调度器:负责调度作 ... -
介绍Quartz
2012-04-27 12:22 1453介绍Quartz Quartz是一个开源的任务调度 ... -
理解Quartz触发器(1)
2012-04-27 11:37 911Quartz中一个Job往往是 ... -
Quartz中SimpleTrigger的探讨
2012-04-27 11:34 7481.来写一个每隔10秒启动一次任务的例子. import j ... -
关于hashcode 里面 使用31 系数的问题
2012-03-27 09:16 879首先我们来了解一下h ... -
理解Java对象序列化
2012-02-15 09:38 733关于Java序列化的文章早 ... -
认识Arrays(一)打印
2012-02-03 16:52 616Arrays提供了一组操作array的静态方法。 一、基本类 ... -
apache.commons.io 笔记1
2012-01-19 17:13 1107看看,常见的东西都有了,如查询盘的剩余空间,文件夹大小, ... -
commons-io 自动加载配置文件
2012-01-19 16:55 828org.apache.commons.io.monitor.F ... -
oracle java数据类型对应表
2011-12-05 13:37 0[img]http://dl.iteye.com/upload ...
相关推荐
总的来说,调用外部程序和与其通信是软件开发中的重要技能,熟练掌握这些技巧能帮助我们构建更加复杂和强大的系统。无论是简单的启动一个应用,还是进行复杂的进程间通信,理解这些概念和技术都将对我们的IT职业生涯...
这个压缩包“基于Matlab调用外部程序操作文件案例(源码+数据+使用说明).rar”提供了一个具体示例,教导用户如何在MATLAB中调用外部程序来处理文件。下面我们将深入探讨这一主题。 首先,MATLAB的`system`函数是...
在IT行业中,调用外部服务来增强应用功能是一种常见的做法,比如使用有道翻译API来实现文本翻译。本文将详细讲解如何在Java环境下调用有道翻译API,以实现高效、便捷的多语言翻译功能。 首先,有道翻译API提供了一...
总之,Java调用Python脚本是一个实用的技巧,它允许开发者结合两种语言的优点,提高代码的可维护性和复用性。通过理解上述概念和实践,你可以灵活地在Java项目中嵌入Python功能。如果有任何疑问,可以参考解压后的...
本文将详细探讨如何利用Java调用Linux命令,这一技能对于任何希望在Java应用中集成Linux功能的开发者来说都是至关重要的。 ### Java调用Linux命令的方法 Java提供了多种方式来执行外部命令或脚本,其中最常用的是...
在本文中,我们将深入探讨如何使用Java来调用外部的.exe可执行文件,以及与之相关的编程技巧。这个名为"AllDialogTest-Java.rar_DEMO_java调用exe"的压缩包包含了一个Java编写的Demo,它演示了如何在Java程序中打开...
标题中的“PB控制运行其他程序(源码)”指的是使用PowerBuilder(PB)开发的应用程序能够启动和管理外部程序的执行。在PowerBuilder中,通过调用操作系统级别的API函数或者使用特定的库函数,可以实现这样的功能。这...
MATLAB提供了多种调用外部程序的方式,包括调用其他MATLAB程序、C/C++程序、Java程序以及操作系统命令。以下将详细介绍这些调用方法。 1. **调用MATLAB程序(.m文件)** MATLAB程序通常以.m为扩展名,它们是MATLAB...
2. **封装**:Java通过访问修饰符实现数据封装,保护类的内部数据不被外部随意访问。源代码中会展示如何使用private、public和protected等关键字控制成员变量和方法的访问权限。 3. **继承**:Java支持单继承和多层...
这个`main`方法定义了程序的起点,Java虚拟机(JVM)通过调用这个方法来启动应用程序。 首先,让我们来看看`main`方法的声明格式: ```java public static void main(String[] args) ``` - `public`: 这个修饰符...
### Java调用Shell脚本和Python脚本及处理输出结果详解 #### 一、引言 在实际开发过程中,我们经常需要在Java程序中调用Shell脚本或Python脚本来执行一些特定的任务,比如系统管理任务、数据分析等。Java通过`java...
调试技巧,如使用IDE的断点、单步执行、查看变量值等,也是学习Java的重要部分。 【总结】 《清华Java程序设计实例教程》全面覆盖了Java编程的基础知识和面向对象编程的概念,结合实例帮助读者理解和应用。通过...
Java调用FFmpeg实现视频转换涉及到Java编程语言和FFmpeg多媒体处理工具的使用。FFmpeg是一个非常强大的命令行工具,支持几乎所有的视频文件格式转换。在Java中调用FFmpeg,通常使用Runtime或者ProcessBuilder类来...
### Java程序员面试技巧详解 #### 面向对象的四大特征 在Java面试过程中,面试官经常会提问关于面向对象的基本概念及其特征。了解并掌握这些基本概念对于通过面试至关重要。 **1. 抽象** 抽象是指在编程时,只...
- Java提供了`java.lang.Runtime.exec(String command)`方法用于调用外部程序。但是需要注意的是,不同的操作系统有不同的命令行语法和程序路径。例如,在Windows下调用`notepad.exe`,而在Linux下则应调用`vi`。 - ...
《Java面向对象程序设计》是一本深入探讨Java编程语言中面向对象特性的经典教材。这本书通过丰富的实例,...书中每个例子都是精心设计,旨在帮助读者逐步掌握Java的面向对象编程技巧,为日后的开发工作打下坚实的基础。
Java面向对象程序设计是软件开发中的重要概念,它基于“对象”的思想,使得代码更加模块化,易于理解和维护。这个基础实例将引导初学者逐步掌握Java面向对象编程的基本原理和实践技巧。 首先,我们需要理解“面向...
`main()`方法是Java程序的入口点,由JVM(Java虚拟机)自动调用。`System.out.println()`是一个常用的方法,用于向控制台打印输出。 2. **类的基本组成示例**: 类是Java中面向对象编程的基础,它包含了变量(属性...
JMeter 可以通过 `java.lang.ClassLoader` 类加载外部 jar,并使用 `java.lang.reflect.Method` 来执行方法。你需要确保 JMeter 的 classpath 包含了这个 .jar 文件,或者将其放在 JMeter 的 lib 目录下。 在实际...
1. **基础语法**:Java的基础语法包括变量、数据类型(如基本类型和引用类型)、运算符、流程控制语句(如if、for、while、switch)、方法定义和调用等。源代码文件中可能会展示这些基本元素的使用。 2. **类与对象...