|
2012年8月20日
在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 同步方式拉取消息,暫時沒找到好的封裝,只能暫時用這?;蛘弑M量用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,建議上面的那種發廣播的方式。
檢測磁盤相關信息 smartctl -a /dev/sda (smartctl工具來自smartmontools, 可以apt-get install smartmontools來安裝) 檢測所有raid設備 mdadm -Ds 檢測具體raid設備信息 mdadm -D /dev/md0 創建raid設備 mdadm --create --verbose /dev/md0 --level=raid0 --raid-devices=8 /dev/sdd /dev/sdc /dev/sdf /dev/sde /dev/sdg /dev/sdh /dev/sdi /dev/sdj
停止raid設備 mdadm -S /dev/md0 格式化raid設備 mkfs -t xfs -f /dev/md0 掛載raid設備 mount -t xfs /dev/md0 /raid 切換raid模式的步驟 1. umount if mounted : umount /raid 2. stop raid device: mdadm -S /dev/md0 3. create raid: mdadm --create ... 4. update /etc/mdadm.conf with output of 'mdadm -Ds', 用來開機自動組raid 5. update /etc/fstab, 如果需要開機自動mount Ref: http://francs3.blog.163.com/blog/static/40576727201212145744783/ http://hi.baidu.com/powersaven/item/1da2dc147a8be2e25f53b19e
關于 alternatives的用法 alternatives --install /usr/bin/java java /opt/jdk1.5.0_22/bin/java 15000 alternatives --install /usr/bin/javac javac /opt/jdk1.5.0_22/bin/javac 15000 alternatives --config java alternatives --config javac
最近切換桌面環境到ubuntu, 發現 alternatives這個工具改名了:update-alternatives 用法還是一樣的。。
直接上C的實現 typedef struct Foo { int len; char name[100]; } Foo_t;
JNIEXPORT jint JNICALL Java_TestJNI_foo(JNIEnv *env, jobject obj, jobject fooObj) {
Foo_t * bar = malloc(sizeof(Foo_t)); jclass clazz; jfieldID fid;
//init the bar data of C strcpy(bar->name, "Yachun Miao"); bar->len = strlen(bar->name);
// mapping bar of C to foo clazz = (*env)->GetObjectClass(env, fooObj); if (0 == clazz) { printf("GetObjectClass returned 0\n"); return (-1); } fid = (*env)->GetFieldID(env, clazz, "len", "I"); (*env)->SetLongField(env, fooObj, fid, bar->len);
fid = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); jstring name = (*env)->NewStringUTF(env, bar->name); (*env)->SetObjectField(env, fooObj, fid, name);
free(bar); return 0; } 對應的Java調用 public class Foo { protected int len; protected String name; }

private static native int foo(Foo fooObj);
public static void main(String args[]) { System.loadLibrary("mylib");
Foo foo = new Foo(); foo(foo); System.out.println(foo.name); System.out.println(foo.len);
} 參考鏈接 http://www.steveolyo.com/JNI/JNI.html#CSTRCJ http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html
平時要用惡心的citrix Xenapp & citrix receiver 工作環境,裝完后發現client端不能復制內容到server端,這樣會對工作造成很大的困擾。 偶然發現citrix receiver的進程上有個-file的選項,會指定個臨時配置文件,里面提及 ClipboardAllowed=off 于是grep下這個關鍵字,發現~/ICAClient/linuxx86/config/All_Regions.ini 也有個類似的 ClipboardAllowed=* 改為 ClipboardAllowed=true 然后重新開Xenapp session之后發現已經可以黏貼了。 按照這個思路,使用windows的同事使用如下的方式打通兩端clipboard 1. 打開系統注冊表編輯器 2. 定位HKEY_CURRENT_USER\Software\Citrix\ICA Client\Engine\Lockdown Profiles\All Regions\Lockdown\Virtual Channels\Clipboard 3. 修改ClipboardAllowed為1 4. 注銷當前用戶(或許需要) 如果Xenapp server上使用vnc viewer之類的Xclient,如果想打通到vnc server的clipboard,還需要在vnc server所在linux主機開啟以下進程 vncconfig -nowin & 這個有點不理解,但確實可行。待真相。。
miaoyachun@ymiao:~$ /usr/lib/i386-linux-gnu/ibus/ibus-x11 --kill-daemon ^Z [1]+ Stopped /usr/lib/i386-linux-gnu/ibus/ibus-x11 --kill-daemon miaoyachun@ymiao:~$ bg [1]+ /usr/lib/i386-linux-gnu/ibus/ibus-x11 --kill-daemon & miaoyachun@ymiao:~$
然后就可以了。。
今天發現ubunto12.4沒有默認的瀏覽器,導致所有的鏈接打開的時候從用gedit。google上找到了解決方法: 編輯以下內容: [Desktop Entry] Version=14.0 Name=Mozilla Firefox Web Browser Comment=Browse the World Wide Web GenericName=Web Browser Keywords=Internet;WWW;Browser;Web;Explorer Exec=/opt/firefox/firefox %u Terminal=false X-MultipleArgs=false Type=Application Icon=firefox Categories=GNOME;GTK;Network;WebBrowser; MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall; StartupNotify=true Actions=NewWindow;
到文件~/.local/share/applications/firefox.desktop, 并保存退出。 執行: update-desktop-database ~/.local/share/applications/
配好以后"System Settings -> Detail -> Default Applications -> Web" list里就會有firefox了。 Ref: http://askubuntu.com/questions/166455/how-do-i-make-luakit-my-default-browser
|