|
2012年11月27日
在Spring cloud config出来之前, 自己实现了基于ZK的配置中心, 杜绝了本地properties配置文件, 原理很简单, 只是重载了PropertyPlaceholderConfigurer的mergeProperties(): /** * 重载合并属性实现 * 先加载file properties, 然后并入ZK配置中心读取的properties * * @return 合并后的属性集合 * @throws IOException 异常 */ @Override protected Properties mergeProperties() throws IOException { Properties result = new Properties(); // 加载父类的配置 Properties mergeProperties = super.mergeProperties(); result.putAll(mergeProperties); // 加载从zk中读取到的配置 Map<String, String> configs = loadZkConfigs(); result.putAll(configs); return result; } 这个实现在spring项目里用起来还是挺顺手的, 但是近期部分spring-boot项目里发现这种placeholder的实现跟spring boot的@ConfigurationProperties(prefix = "xxx") 不能很好的配合工作, 也就是属性没有被resolve处理, 用@Value的方式确可以读到, 但是@Value配置起来如果属性多的话还是挺繁琐的, 还是倾向用@ConfigurationProperties的prefix, 于是看了下spring boot的文档发现 PropertySource order: * Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active). * @TestPropertySource annotations on your tests. * @SpringBootTest#properties annotation attribute on your tests. * Command line arguments. * Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property) * ServletConfig init parameters. * ServletContext init parameters. * JNDI attributes from java:comp/env. * Java System properties (System.getProperties()). * OS environment variables. * A RandomValuePropertySource that only has properties in random.*. * Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants) * Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants) * Application properties outside of your packaged jar (application.properties and YAML variants). * Application properties packaged inside your jar (application.properties and YAML variants). * @PropertySource annotations on your @Configuration classes. * Default properties (specified using SpringApplication.setDefaultProperties). 不难发现其会检查Java system propeties里的属性, 也就是说, 只要把mergerProperties读到的属性写入Java system props里即可, 看了下源码, 找到个切入点 /** * 重载处理属性实现 * 根据选项, 决定是否将合并后的props写入系统属性, Spring boot需要 * * @param beanFactoryToProcess * @param props 合并后的属性 * @throws BeansException */ @Override protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException { // 原有逻辑 super.processProperties(beanFactoryToProcess, props); // 写入到系统属性 if (writePropsToSystem) { // write all properties to system for spring boot Enumeration<?> propertyNames = props.propertyNames(); while (propertyNames.hasMoreElements()) { String propertyName = (String) propertyNames.nextElement(); String propertyValue = props.getProperty(propertyName); System.setProperty(propertyName, propertyValue); } } } 为避免影响过大, 设置了个开关, 是否写入系统属性, 如果是spring boot的项目, 就开启, 这样对线上非spring boot项目做到影响最小, 然后spring boot的@ConfigurationProperties完美读到属性; 具体代码见: org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { ConfigurationProperties annotation = AnnotationUtils .findAnnotation(bean.getClass(), ConfigurationProperties.class); if (annotation != null) { postProcessBeforeInitialization(bean, beanName, annotation); } annotation = this.beans.findFactoryAnnotation(beanName, ConfigurationProperties.class); if (annotation != null) { postProcessBeforeInitialization(bean, beanName, annotation); } return bean; }
Spring默认不允许对类的变量, 也就是静态变量进行注入操作, 但是在某些场景比如单元测试的@AfterClass要访问注入对象, 而Junit的这个方法必须是静态的, 也就产生了悖论; 解决思路有两个: 思路1: 想办法对静态变量注入, 也就是绕过Spring只能运行非静态变量才能注入依赖的壁垒 思路2: 想办法@AfterClass改造为非静态 实现Junit RunListener, 覆盖testRunFinished方法, 这里去实现类似@AfterClass的功能, 这个方法是非静态的 不要用Junit, 改用TestNG, TestNG里的AfterClass是非静态的 用Spring的TestExecutionListeners, 实现个Listener, 里面也有个类似非静态的AfterClass的实现, 覆盖实现就行
思路2的几个方法都可以实现, 但是单元测试Runner需要用 而且改用TestNG工程浩大, 只能放弃掉这个思路 继续走思路1, 只能去绕过Spring的依赖注入的static壁垒了, 具体代码如下: @Autowired private Destination dfsOperationQueue; private static Destination dfsOperationQueueStatic; // static version @Autowired private MessageQueueAPI messageQueueAPI; private static MessageQueueAPI messageQueueAPIStatic; // static version
@PostConstruct public void init() { dfsOperationQueueStatic = this.dfsOperationQueue; messageQueueAPIStatic = this.messageQueueAPI; }
@AfterClass public static void afterClass() { MessageVO messageVO = messageQueueAPIStatic.removeDestination(dfsOperationQueueStatic); System.out.println(messageVO); }
其实就是用了@PostConstruct 来个偷梁换柱而已, 多声明个静态成员指向非静态对象, 两者其实是一个对象
知道activemq现在已经支持了rest api, 但是官方对这部分的介绍一笔带过 (http://activemq.apache.org/rest.html),
通过google居然也没搜到一些有用的, 比如像删除一个destination, 都是问的多,然后没下文. 于是花了一些心思研究了一下:
首先通过rest api获取当前版本所有已支持的协议 http://172.30.43.206:8161/api/jolokia/list
然后根据json输出关于removeTopic, removeQueue的mbean实现通过rest api删除destination的方法, 注意到用GET请求而不是POST,不然会报错 (官网的例子里用的wget给的灵感, 开始用了POST老报错)
import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQTopic; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.DefaultHttpClient; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate;
import javax.jms.Destination; import javax.jms.JMSException; import java.util.Arrays;
public class MessageQueueAdmin { private static final RestTemplate restTemplate = getRestTemplate("admin", "admin");
private static String brokerHost = "172.30.43.206"; private static String adminConsolePort = "8161"; private static String protocol = "http";
public static void removeDestination(Destination destination) throws JMSException { String destName, destType; if (destination instanceof ActiveMQQueue) { destName = ((ActiveMQQueue) destination).getQueueName(); destType = "Queue"; } else { destName = ((ActiveMQTopic) destination).getTopicName(); destType = "Topic"; }
// build urls String url = String.format("%s://%s:%s/api/jolokia/exec/org.apache.activemq:" + "brokerName=localhost,type=Broker/remove%s/%s", protocol, brokerHost, adminConsolePort, destType, destName); System.out.println(url); // do operation HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); System.out.println(response.getBody()); }
public static void main(String[] args) throws JMSException { ActiveMQTopic topic = new ActiveMQTopic("test-activemq-topic"); removeDestination(topic); }
private static RestTemplate getRestTemplate(String user, String password) { DefaultHttpClient httpClient = new DefaultHttpClient(); BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password)); httpClient.setCredentialsProvider(credentialsProvider); ClientHttpRequestFactory rf = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(rf); } }
其他的请求,应该都是类似jolokia的exec get request的格式:
https://jolokia.org/reference/html/protocol.html#exec
<base url>/exec/<mbean name>/<operation name>/<arg1>/<arg2>/.
用Spring JMS 的JmsTemplate从消息队列消费消息时发现,使用了CLIENT_ACKNOWLEDGE模式,消息返回后总是自动被ack,也就是被broker "Dequeued" protected Message doReceive(Session session, MessageConsumer consumer) throws JMSException { try { // Use transaction timeout (if available). long timeout = getReceiveTimeout(); JmsResourceHolder resourceHolder = (JmsResourceHolder) TransactionSynchronizationManager.getResource(getConnectionFactory()); if (resourceHolder != null && resourceHolder.hasTimeout()) { timeout = Math.min(timeout, resourceHolder.getTimeToLiveInMillis()); } Message message = doReceive(consumer, timeout); if (session.getTransacted()) { // Commit necessary - but avoid commit call within a JTA transaction. if (isSessionLocallyTransacted(session)) { // Transacted session created by this template -> commit. JmsUtils.commitIfNecessary(session); } } else if (isClientAcknowledge(session)) { // Manually acknowledge message, if any. if (message != null) { message.acknowledge(); } } return message; } finally { JmsUtils.closeMessageConsumer(consumer); } }
但是使用异步listener 就不会出现这个情况,搜了下google,发现果然存在这个问题 https://jira.spring.io/browse/SPR-12995 https://jira.spring.io/browse/SPR-13255 http://louisling.iteye.com/blog/241073 同步方式拉取消息,暂时没找到好的封装,只能暂时用这。或者尽量用listener, 这个问题暂时标记下,或者谁有更好的解决方案可以comment我
默认的配置有时候点不亮显示器,且分辨率很低,通过tvservice工具不断调试,发现下面的参数可以完美匹配了 修改 /boot/config.txt的下列参数 disable_overscan=1 hdmi_force_hotplug=1 hdmi_group=1 hdmi_mode=16 hdmi_drive=2 config_hdmi_boost=4 dtparam=audio=on
http://stackoverflow.com/questions/3294423/spring-classpath-prefix-difference
SIMPLE DEFINITION
The classpath*:conf/appContext.xml simply means that all appContext.xml files under conf folders in all your jars on the classpath will be picked up and joined into one big application context.
In contrast, classpath:conf/appContext.xml will load only one such file the first one found on your classpath.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:*.properties</value> <value>classpath*:*.properties</value> </list> </property> </bean>
- IDEA_JDK (or IDEA_JDK_64) environment variable
- jre/ (or jre64/) directory in IDEA home
- registry
- JDK_HOME environment variable
- JAVA_HOME environment variable
java里如何修改console的历史输出信息呢?如果是当前行的修改可以简单想到"\r"的方案,但是如果要修改上一行呢? google了下原来还是有方法的,需要用到ansi的control sequences ANSI code用java写了个简单的例子,例子就是把曾经的output修改为其他字符串并恢复之后的打印,代码里加了sleep,主要方便理解各种控制序列的含义 //print some test messages System.out.println("1"); Thread.sleep(1000); System.out.println("22"); Thread.sleep(1000); System.out.println("333"); Thread.sleep(1000); System.out.println("4444"); Thread.sleep(1000);
/** * modify "333" to "-" */ // Move up two lines int count = 2; System.out.print(String.format("\033[%dA", count)); Thread.sleep(1000); // Erase current line content System.out.print("\033[2K"); Thread.sleep(1000); // update with new content System.out.print("-"); Thread.sleep(1000); // Move down two lines System.out.print(String.format("\033[%dB", count)); Thread.sleep(1000); // Move cursor to left beginning System.out.print(String.format("\033[D", count)); // continue print others Thread.sleep(1000); System.out.println("55555"); Thread.sleep(1000);
1. zookeeper basic/fast paxsos 的形象表述 https://www.douban.com/note/208430424/ 2. 详细介绍 http://blog.csdn.net/xhh198781/article/details/10949697
server.compression.enabled=true server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain server.compression.min-response-size=4096 第一个参数打开压缩开关,第二个参数添加json reponse(尤其是为rest api),第三个参数是根据reponse的大小设置启用压缩的最小值(默认是2K,自己根据实际情况调整) 参考 http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#how-to-enable-http-response-compression
介绍centos7如何安装3.0以上的新版本mongodb https://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat/
1. 默认的3个classloader: BootstrapClassloader (Native实现), ExtClassloader, AppClassloader (Java实现) 2. 3个加载器并不是真正的父子继承关系,而是逻辑上的,JVM启动先创建ExtClassloader instance,然后构造AppClassloader的时候传入ExtClassloader实例作为parent Launcher.ExtClassLoader extcl; try { extcl = Launcher.ExtClassLoader.getExtClassLoader(); } catch (IOException var10) { throw new InternalError("Could not create extension class loader", var10); }
try { this.loader = Launcher.AppClassLoader.getAppClassLoader(extcl); } catch (IOException var9) { throw new InternalError("Could not create application class loader", var9); } 关于双亲委派原理: 在加载类的时候,会看看parent有没有设定,如果设定了 就调用parent.loadClass方法,如果没设定(==null)也就是parent应该是BootstrapClassloader, 会调用native的findBootstrapClass来加载类,代码: try { if(this.parent != null) { c = this.parent.loadClass(name, false); } else { c = this.findBootstrapClassOrNull(name); } } catch (ClassNotFoundException var10) { ; }
目的是按照一定优先级别装载系统的lib,系统ext目录的lib,以及classpath的lib,防止系统的默认行为或者类的实现被修改。 3. java 类的动态加载 Java内置的ClassLoader总会在加载一个Class之前检查这个Class是否已经被加载过,已经被加载过的Class不会加载第二次。因此要想重新加载Class,我们需要实现自己的ClassLoader。 另外一个问题是,每个被加载的Class都需要被链接(link),这是通过执行ClassLoader.resolve()来实现的,这个方法是 final的,因此无法重写。Resove()方法不允许一个ClassLoader实例link一个Class两次,因此,当你需要重新加载一个 Class的时候,你需要重新New一个你自己的ClassLoader实例。
maven-shade-plugin 用来打可执行jar包, 可以把所有依赖的三方库都包括进来 exec-maven-plugin 可以执行外部命令, 在项目中对python代码进行编译, 配合maven-assembly-plugin来生成package maven-assembly-plugin 用来构建项目发行包, 要配合xml配置文件来组织包的结构,基本思路是从build环境copy到outputDirectory license-maven-plugin 用来生成项目用到的3方库的版权汇总 或者其他的一些用法 maven-dependency-plugin 用来生成项目库之间的依赖关系 appassembler-maven-plugin 可以为项目生成优雅的启动脚本 支持linux/win rpm-maven-plugin 用来为项目构建rpm安装包 maven-compiler-plugin 指定项目的jdk的编译兼容版本以及encoding类别
快捷键migrating 持续更新
发现一个不错的介绍shell中冒号的用法的文章 http://codingstandards.iteye.com/blog/1160298
项目用mvn exec:exec指令来启动server, 工作中需要调式server初始化的过程, 很容易想到mvnDebug, 但是发现设置的断点都没有hit, 反复调式多次都是如此,折腾了1个多小时, 突然看到stackoverflow 上有人说exec:exec是独立进程模式, mvnDebug的一些debug选项都被append到了父进程了. idea设置断点就然并卵了. 知道了问题所在解决就容易了, 只要修改pom.xml, 然后直接mvn exec:exec就能正常调式了 <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>${mvnexec.version}</version> <executions> <execution> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <includeProjectDependencies>true</includeProjectDependencies> <executable>java</executable> <workingDirectory>${basedir}/config/sim</workingDirectory> <classpathScope>runtime</classpathScope> <arguments> <argument>-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=4000</argument> <argument>-classpath</argument> <classpath/> <argument>com.ymiao.Main</argument> <argument>server</argument> <argument>${basedir}/config/sim/sim.yml</argument> </arguments> </configuration> </plugin> </plugins> </build>
总结就是exec:exec是要独立一个新进程来执行程序的, exec:java就相反, 其实用mvnDebug + exec:java也是理论可行的
After Centos 7.1 tobe installed on my t400, my wireless link "Intel 5100 AGN" cannot be managed by NetworkManager, which show in "PCI unknown" state. Googled many pages, most of them introduced how to scan wifi links by command line tool "iw", i tried all steps supplied by the pages but was blocked at the last step to get dynamical ipaddress by dhclient command "sudo dhclient wlp3s0 -v". The dhclient always complain "NO DHCPOFFERS received." (I doubted there should be some tricky to play with dhclient but which i am not faimiar with.. sad.. ) But i think there would be some extending tool for NetworkManager to manager wifi, then i google "NetworkManager wifi", i got "NetwrokManager-wifi plugin" from link https://www.centos.org/forums/viewtopic.php?f=47&t=52810 After following steps , i finally make wifi work well on centos 7.1 - yum install NetworkManager-wifi
- reboot machine (i tried logout and login, not work)
Problem is NetworkManager-wifi is not installed by default on centos 7.1, (would it be my mistake when install OS? strange..)
http://onlywei.github.io/explain-git-with-d3
项目中要用到MBean,于是快速体验下,体验过程中发现2个问题: - 自定义的Mbean的普通method能在jconsole的Mbeans里显示出来,但是涉及到geters/seters就无法显示了
- 如果MBean注册到下面形式创建的MBeanServer在Jconsole上无法显示的
MBeanServer server = MBeanServerFactory.createMBeanServer(); 但是如果注册到下面的形式创建的Server在Jconsole上是可以显示MBean的
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
stackoverflow上也有人发现这个问题 http://stackoverflow.com/questions/7424009/mbeans-registered-to-mbean-server-not-showing-up-in-jconsole
http://www.ourd3js.com/wordpress/
Two compile issues i got:
One issue is: uuid_gen_unix.c: In function 'axutil_uuid_gen_v1':uuid_gen_unix.c:62:20: error: variable 'tv' set but not used [-Werror=unused-but-set-variable] struct timeval tv; ^cc1: all warnings being treated as errors
Solution is remove "-Werror" in all configure scripts find -type f -name configure -exec sed -i '/CFLAGS/s/-Werror//g' {} \; Another issue is:/usr/bin/ld: test.o: undefined reference to symbol 'axiom_xml_reader_free' /usr/local/axis2c/lib/libaxis2_parser.so.0: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status make[4]: *** [test] Error 1 make[4]: Leaving directory `/home/miaoyachun/softwares/test/axis2c-src-1.6.0/neethi/test'
As suggested in https://code.google.com/p/staff/issues/detail?id=198, the solution is disable neethi/test in following files: Finally, you could run "make; sudo make install"" successfully. Last thing should be paid attention to is you may need copy all head files of neethi/include into /usr/local/axis2c/include/axis2-1.6.0/ which needed when you compile customized web service.
Enjoining it!!
http://axis.apache.org/axis2/c/core/docs/axis2c_manual.html#client_api 的hello.c client 编译命令在我的ubuntu 12.04s上总是报错 gcc -o hello -I$AXIS2C_HOME/include/axis2-1.6.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver -ldl -Wl,--rpath -Wl,$AXIS2C_HOME/lib hello.c /tmp/ccCYikFh.o: In function `main': hello.c:(.text+0x57): undefined reference to `axutil_env_create_all' hello.c:(.text+0x68): undefined reference to `axis2_options_create' hello.c:(.text+0x93): undefined reference to `axutil_strcmp' hello.c:(.text+0xeb): undefined reference to `axis2_endpoint_ref_create' hello.c:(.text+0x102): undefined reference to `axis2_options_set_to' hello.c:(.text+0x13d): undefined reference to `axis2_svc_client_create' hello.c:(.text+0x168): undefined reference to `axutil_error_get_message' hello.c:(.text+0x193): undefined reference to `axutil_log_impl_log_error' hello.c:(.text+0x1b1): undefined reference to `axis2_svc_client_set_options' hello.c:(.text+0x1d6): undefined reference to `axis2_svc_client_send_receive' hello.c:(.text+0x21d): undefined reference to `axiom_node_free_tree' hello.c:(.text+0x238): undefined reference to `axutil_error_get_message' hello.c:(.text+0x266): undefined reference to `axutil_log_impl_log_error' hello.c:(.text+0x28d): undefined reference to `axis2_svc_client_free' hello.c:(.text+0x2a8): undefined reference to `axutil_env_free' /tmp/ccCYikFh.o: In function `build_om_request': hello.c:(.text+0x2ed): undefined reference to `axiom_element_create' hello.c:(.text+0x307): undefined reference to `axiom_element_set_text' /tmp/ccCYikFh.o: In function `process_om_response': hello.c:(.text+0x337): undefined reference to `axiom_node_get_first_child' hello.c:(.text+0x351): undefined reference to `axiom_node_get_node_type' hello.c:(.text+0x367): undefined reference to `axiom_node_get_data_element' hello.c:(.text+0x381): undefined reference to `axiom_text_get_value' hello.c:(.text+0x396): undefined reference to `axiom_text_get_value' collect2: error: ld returned 1 exit status
仔细检查了gcc命令,头文件,库文件的路径都是对的,最后跟同事讨论才发现hello.c的位置的问题。。如果hello.c的位置放到了依赖库的右面 就会报类似错误。但是官方的例子应该是测试过的,怎么会有这个问题呢? 难道我的ubuntu 12.04的gcc比较严格? 修正后的gcc命令如下 gcc -o hello hello.c -I$AXIS2C_HOME/include/axis2-1.6.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver -ldl -Wl,--rpath -Wl,$AXIS2C_HOME/lib
ubuntu 12.04s每次修改limit.conf文件后,要想让所有的后继ssession都能看到修改,一般要么重启系统,要么relogin系统。下面介绍一个不退出terminal就让修改立刻生效的方式 1. 修改/etc/pam.d/sudo,添加下面行到文件末尾 session required pam_limits.so
2. 修改 /etc/security/limits.conf, 比如 root soft nofile 65535 root hard nofile 65535
3. 执行sudo -i -u root 模拟登录初始化 另外发现centos 6系统/etc/pam.d/sudo已经默认enable pam_limits.so了,直接2,3就可以了。 当然如果用ssh重新登录下可能来的更快。。因为/etc/pam.d/sshd默认enable了pam_limits.so, 多输入个密码而已
ss(shadowsocks) 是基于socks5的,但是android studio sdk manager只支持http代理,导致android studio无法更新sdk tools,解决方法就是polipo,可以将socks5转换为http代理 具体方法见 https://github.com/shadowsocks/shadowsocks/wiki/Convert-Shadowsocks-into-an-HTTP-proxy
ubuntu上ibus经常出现不能输入中文的情况,用下面命令可以临时解决问题
ibus-daemon -r &
从jdk7最开始的release version (http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html)的notes里看到
Area: HotSpot Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences. RFE: 6962931
今天有同事问为什么ubuntu上启动jenkins失败,我记得之前玩的时候并没有出现这种情况,于是跟踪了下,最终错误信息是: daemon: fatal: refusing to execute unsafe program: /usr/bin/java (/opt is group and world writable) 根本原因是机器装了多个版本的jdk, jdk所在的/opt父目录的权限放的比较大,按照daemon要求的限制到755 chmod -R 755 /opt 问题就解决了。 其实这个场景还是蛮常见的,遇到的人应该挺多的
latency = client send request time + network trans time (->)+ server receive request time+ reponse time + server send reponse time+ network trans time (<-)+ client receive reponse time
latency = first byte out, last byte in time
以前用centos的chkconfig来管理系统服务,而ubuntu上是没有这个工具的,google上提到一个替代品sysv-rc-conf, apt-get install下就可以直接用了,有个text console可以使用
Java程序的memory leak分析也可以用valgrind, 尤其是JNI程序尤其有用: valgrind --error-limit=no --trace-children=yes --smc-check=all --leak-check=full JAVA_CMD 特意写了个有leak的jni函数,用valgrind成功检查出来了 ==31915== 100 bytes in 1 blocks are definitely lost in loss record 447 of 653 ==31915== at 0x402CE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==31915== by 0x60424F9: Java_MyJNI_hello (MyJNI.c:16)
在老版本valgrind(3.5.0) enable了--trace-children选项后可能出现错误: Error occurred during initialization of VM Unknown x64 processor: SSE2 not supported
升级到最新版可以解决这个问题,升级方法:下载src包 解压后执行 ./configure; make; make install
maven项目中有很多本地三方依赖,但是一个一个加入dependency + system scope又很麻烦,又貌似没有搜索到通配符的成功案例,但是从stackoverflow上看到一个插件addjars-maven-plugin, 可以很好解决这类需求: <build> <plugins> <plugin> <groupId>com.googlecode.addjars-maven-plugin</groupId> <artifactId>addjars-maven-plugin</artifactId> <version>1.0.2</version> <executions> <execution> <goals> <goal>add-jars</goal> </goals> <configuration> <resources> <resource> <directory>${basedir}/../lib</directory> </resource> </resources> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>${maven.assembly.version}</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <appendAssemblyId>false</appendAssemblyId> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> 把项目中依赖的三方jars全放到lib目录里,就全部会打包到release jar里了
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <inttypes.h>
uint64_t htonll(uint64_t val) { return (((uint64_t) htonl(val)) << 32) + htonl(val >> 32); }
uint64_t ntohll(uint64_t val) { return (((uint64_t) ntohl(val)) << 32) + ntohl(val >> 32); } int main() { uint64_t hll = 0x1122334455667788; printf("uint64: %"PRIu64"\n", hll); printf("0x%"PRIX64"\n", hll); printf("htonll(hll) = 0x%"PRIX64"\n", htonll(hll)); printf("ntohll(htonll(hll)) = 0x%"PRIX64"\n", ntohll(htonll(hll))); printf("ntohll(hll) = 0x%"PRIX64"\n", ntohll(hll)); // no change return 1; }
big endian(network byte order), little endian (host byte order in intel arch)
用jd-eclipse 插件来反编译java class文件的输出还是挺nice的,虽然阅读方便了 但是对debug确造成一定的困扰,主要问题是line number的不match. Google了下遇到类似问题的真不少。最终找到了解决方案: http://sourceforge.net/projects/realignmentjd/files/ -----------------
1. Download JD-Eclipse and JD-GUI - http://java.decompiler.free.fr/ and install. 2. Put a file realignment.jd.ide.eclipse_1.0.2.jar in eclipse/plugins directory. To use Realignment feature it is necessary to open the menu Preferences/General/Editors/File Associations and to select "*.class" file type and to choose "Realignment for JD Class File Editor" for Associated editors. Another possibility is the batch realignment after processing JD-GUI. To work properly you must to switch on the property "Display line numbers" in Help/Preferences of JD-GUI. To use this feature it is necessary to open the menu Preferences/Java/Decompiler/Batch Realignment and click button "Open dialog". Existing limitation: the realignment is performed only for the methods. To work properly it is necessary that the property "Display line numbers" in menu "Preferences/Java/Decompiler" was active.
JD-Eclipse插件 + realignment 补丁让优雅的debug class 文件成为可能。 如果只是为了阅读class代码,建议不要用 realignment 补丁,这样会降低代码的可读性(会多出大量的空行)
sudo dpkg -l \*erlang\* Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) ||/ Name Version Description +++-=============================-=============================-========================================================================== ii erlang 1:14.b.4-dfsg-1ubuntu1 Concurrent, real-time, distributed functional language un erlang-abi-13.a <none> (no description available) ii erlang-appmon 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP application monitor ii erlang-asn1 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP modules for ASN.1 support rc erlang-base 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP virtual machine and base applications ii erlang-base-hipe 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP HiPE enabled virtual machine and base applications ii erlang-common-test 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP application for automated testing ii erlang-corba 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP applications for CORBA support ii erlang-crypto 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP cryptographic modules ii erlang-debugger 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP application for debugging and testing ii erlang-dev 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP development libraries and headers ii erlang-dialyzer 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP discrepancy analyzer application ii erlang-diameter 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP implementation of RFC 3588 protocol ii erlang-doc 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP HTML/PDF documentation un erlang-doc-html <none> (no description available) ii erlang-docbuilder 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP application for building HTML documentation ii erlang-edoc 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP module for generating documentation ii erlang-erl-docgen 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP documentation stylesheets ii erlang-et 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP event tracer application ii erlang-eunit 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP module for unit testing ii erlang-examples 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP application examples ii erlang-gs 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP graphics system ii erlang-ic 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP IDL compiler ii erlang-ic-java 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP IDL compiler (Java classes) ii erlang-inets 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP Internet clients and servers ii erlang-inviso 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP trace tool ii erlang-jinterface 1:14.b.4-dfsg-1ubuntu1 Java communication tool to Erlang ii erlang-manpages 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP manual pages ii erlang-megaco 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP implementation of Megaco/H.248 protocol ii erlang-mnesia 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP distributed relational/object hybrid database ii erlang-mode 1:14.b.4-dfsg-1ubuntu1 Erlang major editing mode for Emacs ii erlang-nox 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP applications that don't require X Window System ii erlang-observer 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP application for investigating distributed systems ii erlang-odbc 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP interface to SQL databases ii erlang-os-mon 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP operating system monitor ii erlang-parsetools 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP parsing tools ii erlang-percept 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP concurrency profiling tool ii erlang-pman 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP process manager ii erlang-public-key 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP public key infrastructure ii erlang-reltool 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP release management tool ii erlang-runtime-tools 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP runtime tracing/debugging tools ii erlang-snmp 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP SNMP applications ii erlang-src 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP applications sources ii erlang-ssh 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP implementation of SSH protocol ii erlang-ssl 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP implementation of SSL ii erlang-syntax-tools 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP modules for handling abstract Erlang syntax trees ii erlang-test-server 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP server for automated application testing ii erlang-toolbar 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP graphical toolbar ii erlang-tools 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP various tools ii erlang-tv 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP table viewer ii erlang-typer 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP code type annotator ii erlang-webtool 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP helper for web-based tools ii erlang-x11 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP applications that require X Window System ii erlang-xmerl 1:14.b.4-dfsg-1ubuntu1 Erlang/OTP XML tools
erlang-dev包含头文件,erlang-src包含源代码,erlang-debugger包含调试工具,erlang-base包含虚拟机 还可以根据package 名字的suffix察看erlang man doc,比如 man 3erl erlang man 3erl mnesia man 3erl io
命令行调试erlang程序报错: 2> c(hello, [debug_info]). {ok,hello} 3> im(). Call to i:im/0 in application debugger failed. ok
google之原来是erlang-debugger没装 sudo apt-get install erlang-debugger 然后Monitor窗口就出来了。不过用eclipse 的erlide插件调试也可以。
mvn 执行外部命令命令行模式 mvn exec:exec -Dexec.executable=sh -Dexec.workingdir=./bin -Dexec.args=hello.sh 配置文件形式 <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <execution> <id>test-exec</id> <phase>initialize</phase> <configuration> <executable>sh</executable> <workingDirectory>./bin</workingDirectory> <arguments> <argument>hello.sh</argument> </arguments> </configuration> <goals> <goal>exec</goal> </goals> </execution> </executions> </plugin>
mvn 生成java项目生成骨架 mvn archetype:generate -DgroupId=com.abc.product -DartifactId=product -DpackageName=com.abc.product -DarchetypeArtifactId=maven-archetype-quickstart 转成eclipse能识别的java 项目 mvn eclipse:eclipse 导入eclipse 然后coding mvn进行单元测试 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.12.4</version> <configuration> <forkMode>pertest</forkMode> <excludes> <exclude>**/perftest/*.java</exclude> </excludes> <systemProperties> <property> <name>log4j.configuration</name> <value>target/test-classes/log4j.properties</value> </property> </systemProperties> </configuration> </plugin>
mvn进行code coverage统计 <reporting> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>emma-maven-plugin</artifactId> <version>1.0-alpha-3</version> <inherited>true</inherited> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>surefire-report-maven-plugin</artifactId> <inherited>true</inherited> </plugin> </plugins> </reporting>
mvn生成javadoc
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>2.9</version> <configuration> <show>private</show> </configuration> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>javadoc</goal> <goal>test-javadoc</goal> </goals> <phase>site</phase> </execution> </executions> </plugin>
最近项目要用JNI, 涉及到用java.library.path这个参数,开始以为只要ldconfig能识别到的so文件java 一定能找到,可惜并不是这样。。 要想java程序找到共享库还是要在执行java程序的时候指定java.library.path,用eclipse的话可以设置如下: Properties->Run/Debug settings->Arguments->VM arguments ----------------------------------------- -Djava.library.path=/home/miaoyachun/workspace/JNIC/Release 这个是传统的方式,google了下有个tricky的方式让程序动态修改java.library.path private static void loadJNILibDynamically() { try { System.setProperty("java.library.path", System.getProperty("java.library.path") + ":/home/miaoyachun/workspace/JNIC/Release/"); Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); fieldSysPath.setAccessible(true); fieldSysPath.set(null, null);
System.loadLibrary("JNIC"); } catch (Exception e) { // do nothing for exception } } 事实上linux下还有个环境变量LD_LIBRARY_PATH,如果lib能在这个path里找到,java.library.path就不用配置了,而且不需要关心lib之间依赖的问题。java.library.path在这方面就弱很多,比如lib依赖其他目录的lib等。
今天有同事反应一个网络现象,一个多网卡环境,发给eth1的数据包都被eth0接收了。 第一印象是arp的问题。Google了下得到了确认,有个相关的kernal参数: arp_ignore - INTEGER Define different modes for sending replies in response to received ARP requests that resolve local target IP addresses: 0 - (default): reply for any local target IP address, configured on any interface 1 - reply only if the target IP address is local address configured on the incoming interface 2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface 3 - do not reply for local addresses configured with scope host, only resolutions for global and link addresses are replied 4-7 - reserved 8 - do not reply for all local addresses 默认是0,解决这个问题需要配置为1 临时配置下 sysctl -w net.ipv4.conf.all.arp_ignore=1 持久配置 sysctl -w net.ipv4.conf.all.arp_ignore=1 echo 'net.ipv4.conf.all.arp_ignore=1' >> /etc/sysctl.conf 这个弄好可以重启network服务来确保其他机器更新arp cache,如果不方便重启network,自己手动敲arping命令,比如 arping -q -A -c 1 -I eth1 10.197.24.177 这个命令是在 /etc/sysconfig/network-scripts/ifup-eth里看到的 如果机器比较少,也可以直接用arp -d 来删除相关的cache,建议上面的那种发广播的方式。
|