java.lang.UnsatisfiedLinkError: no XXX in java.library.path

其中涉及的测试源码如下:

For those who didn’t install Java with default settings, a systematic way for solving JNI class path problem is:
1> include “System.out.println(System.getProperty(“Java.library.path”)); ” in your “static” block, right before loading the class.
2> run your program and not surprisingly you got the err again, but this time with java.library.path info for your system. (it’s important since this path name varies among systems).
3> cp your libxxx.so into the java.library.path

 

Java一般使用两个path:classpath 和 java.library.path

classpath是指向jar包的位置

java.library.path是非java类包的位置如(dll,so)

解决办法:

第一种方法,在代码里设置环境变量

第二种方法:执行时在vm arguments里添加-Djava.library.path= /usr/local/lib,例如java -Djava.library.path=.   xxx(xxx是某个类文件的名字,不包括后缀)

第三种方法:设置环境变量java.library.path

1:Linux下的系统变量LD_LIBRARY_PATH来添加java.library.path

2:Windows下设置哪个环境变量???????????????????

 

如果你上面看不懂的话就继续向下面看:
1、 在你载入jni类之前 放入“System.out.println( System.getProperty(“java.library.path”));
2、运行你的程序你将获得java.library.path指向的目录
3、拷贝你的libxxx.so到java.library.path指向的某个目录下面。
注意:
Linux下:一定要将Linux下的共享库(我暂且这么叫:)命名成libxxx.so的形式,”xxx”是你在System.loadLibrary(“xxx“)中用到的加载库名称。

Windows下:一定要将Windows下的共享库(我暂且这么叫:)命名成xxx.dll的形式(没有前边的lib三个字母),”xxx”是你在System.loadLibrary(“xxx“)中用到的加载库名称。

 

查了其他的资料:
也可以通过设置LINUX下的系统变量LD_LIBRARY_PATH来添加java.library.path,只要在启动~/.bashrc中添加如下代码然后重新登录shell,就可以将动态库放在当前目录下运行你的jni程序了。
export LD_LIBRARY_PATH=.:..:$LD_LIBRARY_PATH

另外也可以通过如下I’m new to JNI. I see there are several ways to set JVM to look for libraries dll, so, etc.

 

System.setProperty(“java.library.path”, “.”);
System.loadLibrary(“hello”);
That’s when UnsatisfiedLinkError

java.lang.UnsatisfiedLinkError: no hello in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)
at java.lang.System.loadLibrary(System.java:992)
at HelloWorld.main(HelloWorld.java:17)

CORS(Cross-Origin Resource Sharing) 跨域资源共享

2013-01-29     
CORS

全称:Cross-Origin Resource Sharing

中文意思:跨域资源共享?

好吧,目前中文方面的资料还比较少,能搜索到的那仅有的几篇相关介绍,也几乎是雷同的。

最近工作上也有用到CORS的地方,随便做点分享吧,也当是笔记。

 

大家也知道,XMLHttpRequest接口是Ajax的根本,而Ajax考虑到安全性的问题,是禁止跨域访问资源的。

也就是说:www.a.com的页面无法通过Ajax来调用www.b.com的资源。

很多人又会说,但jQuery的$.ajax()明明就可以跨域访问啊!

对,的确是跨了,但那是jsonp!关于jsonp的介绍也很多了,这里不扯。

其实jQuery的$.ajax()方法中,也可以实现CORS,只要服务器端配合,跨域就不需要使用jsonp。

 

CORS是XMLHttpRequest Level 2中新增加的功能

支持情况如下

\

支持情况还算良好(假如无视IE的话)。

移动端的开发,除了Opera Mini还不支持,其他设备的版本支持情况也很好。

 

 

好了,下面进入实战,直接说说使用方法。

1 var xhr = new XMLHttpRequest();
2 xhr.open(“POST”, “http:// www.2cto.com “, true);
3 xhr.send();没有看错!就是这么简单!

和Ajax的调用方法是毫无差异的,需要的只是服务器端的配合。

 

服务器端如何配置?

PHP:只需要使用如下的代码设置即可。

1 <?php
2  header(“Access-Control-Allow-Origin:*”); 以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。

当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。

如果仅支持www.a.com这个站跨域访问,那就:

1 <?php
2  header(“Access-Control-Allow-Origin: http://www.a.com”); 这样就基本配置ok了~

 

前端的部分,如果需要跨域向服务器发cookies

还需要设置一个属性:withCredentials

1 var xhr = new XMLHttpRequest();
2 xhr.open(“POST”, “http://www.b.com”, true);
3 xhr.withCredentials = true; //支持跨域发送cookies
4 xhr.send(); 当然,服务器端也要设置

1 <?php
2 header(“Access-Control-Allow-Credentials: true”);

 

好吧,下面说说需要注意的地方。

如果不使用第三方库,用原生javascript来写,还是有些地方需要注意的。

 

1、不要设置X-Requested-With头

因为跨域访问,如需带header,服务器端必须要allow,不然报错。

setRequestHeader(“X-Requested-With”, “XMLHttpRequest”)主要用在Ajax调用资源时,服务器能判断该次请求是Ajax的。

 

2、INVALID_STATE_ERR: DOM Exception 11

这是一个神奇的错误,网上找了一下,也没什么较为明确的答复。但我却在手机端遇到了这个问题!

测试了一下:在IOS4和IOS5的UC浏览器、Safari、Chrome,进行CORS访问均会报这个错,

Android4.0原生浏览器,也无法正常CORS(没有测试2.3和2.2)

估计也是报这个错,但没控制台,所以无法查bug。

Android4.0下的Chrome和UC都可以顺利CORS。

本以为是浏览器兼容的问题,经过蛋疼的排查之后,发现…

我们可以看一下,下面两段代码有啥差异?

1 var xhr = new XMLHttpRequest();
2 xhr.withCredentials = true; //支持跨域发送cookies
3 xhr.open(“POST”, “http://weibo.com/demo/b/index.php”, true);
4 xhr.send();1 var xhr = new XMLHttpRequest();
2 xhr.open(“POST”, “http://weibo.com/demo/b/index.php”, true);
3 xhr.withCredentials = true; //支持跨域发送cookies
4 xhr.send();唯一的差异就是xhr.withCredentials = true; 的位置。

但就是这个差别,导致第一段代码无法顺利在手机端运行,并报INVALID_STATE_ERR: DOM Exception 11这个错!

而在桌面版浏览器下,两段代码都可以顺利运行!

所以,以后设置withCredentials属性时,一定要在open方法之后!

 

篇幅有限,想要参考更多的CORS,可以查看下面的参考网站.

 

参考:

http://www.w3.org/TR/cors/

http://www.html5rocks.com/en/tutorials/cors/

https://developer.mozilla.org/en-US/docs/HTTP_access_control  (MDN十分详细的讲解)

http://enable-cors.org/index.html (不同的服务器怎么配置CORS)

http://people.opera.com/tiffanyb/2011/cors/ (来自Opera的CORS测试Demo)

http://arunranga.com/examples/access-control/ (另一个CORS的测试Demo)

JNI方法签名–JNI中C如何调用Java的类方法时用到

JNI方法签名

ref:http://www.cnblogs.com/shaweng/p/4013320.html

为什么会有方法签名这种东西呢?这是因为Java这边支持函数重载,即虽然参数不一样,但是方法名一样,那么在JNI层它们的方法名都会是一样的,那JNI也会犯迷糊了,得找哪个呢?

不过也正是因为其参数类型是不一样的,所以就出现了方法签名,利用方法签名和方法名来唯一确定一个JNI函数的调用。
既然方法签名是基于参数类型的不同而形成的,首先要知道Java各数据类型对应的签名是什么,也就是所谓的类型签名,
在jni.h文件中就已经定义了这样一套规则,如下:

1
2
3
4
5
6
7
8
9
10
11
typedef union jvalue {
    jboolean    z;
    jbyte       b;
    jchar       c;
    jshort      s;
    jint        i;
    jlong       j;
    jfloat      f;
    jdouble     d;
    jobject     l;
} jvalue;

对应于Java端的数据类型,我们也可以看一下下面的表:

Java 类型 类型签名
boolean Z
byte B
char C
short S
int I
long L
float F
double D
L全限定名;,比如String, 其签名为Ljava/lang/util/String;
数组 [类型签名, 比如 [B

对于上面的类,要注意其后面还有一个分号。
而对一个方法,其签名就是其参数类型签名和返回值类型签名的字符串,其形式如下:
(类型签名1类型签名2…)返回值类型签名
每个类型签名之间是没有空格的,下面看看两个例子:

有方法 1):

1
public string addTail(String tail, int index)

其对应的签名如下:

1
(Ljava/util/String;I)Ljava/util/String;

方法 2):

1
public int addValue(int index, String value,int[] arr)

其对应的签名如下:

1
(ILjava/util/String;[I)I

相信通过这两个例子,大家也能够了解了方法签名是什么样的形式了吧,对于JNI这些奇形怪状的表示形式也有一定的了解了。

使用GWT的第一个程序

source: http://blog.csdn.net/qq7342272/article/details/6924065

 

今天头一次接触GWT写了一个welcome页面,感觉GWT不是特别难。只不过缺点是没有中文的API哭  (我也不懂英文,,肿么办?  google翻译呗。。)  还有刚刚编译的时候死慢。。 不过修改代码后直接刷新页面后就可以看到新的效果了。对于这点洒家还是比较满意的。生气至少不用每次都经过漫长的编译过程。。  好了不多说废话了。下面就开始我们的GWT之旅。

第一步

1、eclipse 我的是3.7

2、eclipse插件

至于怎么安装ecli[se我就不说了 百度一搜一堆

下面说说具体怎么装gwt的插件。

1、安装eclipse的GWT插件:打开eclipse–help–Insall New Software  点击Add 然后填写Name(这个随便了。。我写的是GWT)Location写http://dl.google.com/eclipse/plugin/3.7填写后点击确定出现一堆要选择的插件。。具体选哪个我也不晓得 只能全选上了- –  点击Next然后等待漫长的下载。。

2、安装GWT的SDK:这个需要去google自行下载了。。。要根据eclipse的版本去下载。  这个是地址:http://code.google.com/intl/zh-CN/eclipse/docs/download.html 可以用google浏览器翻译成中文。。  google浏览器对不懂英语的童鞋是一大福利啊。下载后解压任意目录。。

3、下载GWT的插件:GWT的插件需要有WST插件的支持,可以到eclipse官方下载WST插件。下载完成后把zip中的features和plugins子目录解压到eclipse的安装目录的dropins目录即可。

4、配置:以上工作完成后,启动eclipse程序 选择windows–Perferences菜单 弹出Perferences对话框 咱开google–Web Toolkit配置节点点击Add 弹出添加SDK对话框,输入SDK解压目录 然后给SDK起一个唯一的名称

点击OK 重启eclipse

—————————华丽的分割线———————————–

到这里gwt的插件已经配置完成了。

下面我们做gwt的第一个程序。

安装完成后eclipse的工具栏会多出几个gwt的工具。 如图

选择那个蓝色的 google Development Tools–New Web Appliction Project 新建gwt项目

然后项目名啊 包名啊什么的就不说了 直接finish完成

删除src下client下的GreetingService.java、GreetingServiceAsync.java和server目录

war下的web.xml中servlet和servlet-mapping也要删除

打开war目录下的WelcomeGwt.html 简化成一个普通的html文件

注意 里面有个javascript的引用,这个不需要删除。

打开src–zhy–client下的welcomeGwt.java删除所有内容(清空类内的所有代码)编写代码

  1. package zhy.client;
  2. import com.google.gwt.core.client.EntryPoint;
  3. import com.google.gwt.event.dom.client.ClickEvent;
  4. import com.google.gwt.event.dom.client.ClickHandler;
  5. import com.google.gwt.user.client.Window;
  6. import com.google.gwt.user.client.ui.Button;
  7. import com.google.gwt.user.client.ui.RootPanel;
  8. public class WelcomeGwt implements EntryPoint {
  9.     //这个是页面加载时执行的代码
  10.     @Override
  11.     public void onModuleLoad() {
  12.         Button btn=new Button(“我的第一个GWT按钮”);  //新建一个按钮
  13.         //给按钮添加单击事件
  14.         btn.addClickHandler(new ClickHandler() {
  15.             @Override
  16.             public void onClick(ClickEvent event) {
  17.                 Window.alert(“你好”);//调用windows的弹窗
  18.             }
  19.         });
  20.         RootPanel.get().add(btn);  //把按钮添加到页面中
  21.     }
  22. }

 

点击Run As 选择Run As–Web Appliction启动

然后就是漫长的编译过程 eclipse输出这个的时候 右键 open

自己可以配置一下eclipse的默认浏览器。  我选的是google

到这里就完成第一个gwt程序了。 后续继续更新gwt其他的文章  觉得好的话就赞一下吧。。 一步一步的截图 打字 好累的说。。。

Eclipse 3.7.2 download

Eclipse IDE for Java EE Developers, 212 MB

Windows 32 Bit
Windows 64 Bit

 

Eclipse Classic 3.7.2, 174 MB
Windows 32 Bit
Windows 64 Bit

 

Eclipse for RCP and RAP Developers, 181 MB

 

Java 7u4
Windows 脱机 (64 位) 文件大小: 20.9 MB http://javadl.sun.com/webapps/download/AutoDL?BundleId=63692
Windows 脱机 (32 位) 文件大小: 20.1 MB http://javadl.sun.com/webapps/download/AutoDL?BundleId=63691

spring执行定时任务

定义一个任务是很简单的实现TimerTask的run方法就可以了.
如下:SayHelloTask.java

package test.timerTask;

import java.util.TimerTask;

public class Task extends TimerTask {

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(“测试TimerTask : Hello !!”);
}

}

package test.springTimer;

import java.util.TimerTask;

public class Task2 extends TimerTask{
public void run(){

System.out.println(“task2 is running”);
}

}

然后是配置文件:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd“>

<beans>
<bean id=”sayHelloTask”></bean>
<bean id=”HelloTask”></bean>

<bean id=”scheduledTask”>
<property name=”timerTask”>
<ref bean=”sayHelloTask”/>
</property>
<!– 任务执行周期 2m 关于一些任务的参数请参考JDK doc文档和Spring相关文档–>
<property name=”period”>
<value>2000</value>
</property>
<!– 延时1m 执行任务 –>
<property name=”delay”>
<value>1000</value>
</property>
</bean>
<bean id=”scheduledTask2″>
<property name=”timerTask”>
<ref bean=”HelloTask”/>
</property>
<!– 任务执行周期 2m 关于一些任务的参数请参考JDK doc文档和Spring相关文档–>
<property name=”period”>
<value>2000</value>
</property>
<!– 延时1m 执行任务 –>
<property name=”delay”>
<value>1000</value>
</property>
</bean>
<!– 启动定时器 –>
<bean id=”timerBean”>
<property name=”scheduledTimerTasks”>
<list>
<ref bean=”scheduledTask”/>
<ref bean=”scheduledTask2″/>
</list>
</property>
</bean>
</beans>

 

测试类如下:TestApp.java

package test.timerTask;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestApp {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context = new ClassPathXmlApplicationContext(“test/timerTask/javaTimer.xml”);
//   ApplicationContext context2 = new ClassPathXmlApplicationContext(“test/timerTask/quartzTimer.xml”);
}
// 只要加载配置文件就可以了,
}

运行结果:
task2 is running
task2 is running
haha,task is running
haha,task is running
task2 is running

使用Java中的定时器比较简单,其提供的任务也比较简单, 下面来看看使用quartz来执行一个复杂的任务.

package test.timerTask;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class SayHelloTaskUsingQuartz extends QuartzJobBean {

@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println(“使用Quartz 认为调度: Hello!!”);
}

}

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd“>
<bean id=”sayHelloJob” class=”org.springframework.scheduling.quartz.JobDetailBean”>
<property name=”jobClass”>
<value>test.timerTask.SayHelloTaskUsingQuartz</value>
</property>
</bean>

<!– 关键在如下两个触发器的配置 –>

<!– 类似于Java的简单触发器 –>

<bean id=”helloTrigger” class=”org.springframework.scheduling.quartz.SimpleTriggerBean”>
<property name=”jobDetail”>
<ref bean=”sayHelloJob”/>
</property>
<property name=”startDelay”>
<value>1000</value>
</property>
<property name=”repeatInterval”>
<value>3000</value>
</property>
</bean>

<!– 复杂触发器 –>

<bean id=”helloCronTrigger” class=”org.springframework.scheduling.quartz.CronTriggerBean”>
<property name=”jobDetail”>
<ref bean=”sayHelloJob”/>
</property>
<property name=”cronExpression”>

<!– 关键在配置此表达式 –>

<value>0 49 15 * *  </value>
</property>
</bean>
<bean id=”scheduler” class=”org.springframework.scheduling.quartz.SchedulerFactoryBean”>
<property name=”triggers”>
<ref bean=”helloCronTrigger”/>
</property>
</bean>

</beans>


关于简单触发器和复杂触发器,查考下面的解释:

Quartz设计者做了一个设计选择来从调度分离开作业。Quartz中的触发器用来告诉调度程序作业什么时候触发。框架提供了一把触发器类型,但两个最常用的是SimpleTrigger和CronTrigger。SimpleTrigger为需要简单打火调度而设计。典型地,如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,如果你有许多复杂的作业调度,那么或许需要CronTrigger。

CronTrigger是基于Calendar-like调度的。当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。

作为一个例子,下面的Quartz克隆表达式将在星期一到星期五的每天上午10点15分执行一个作业。
0 15 10   * MON-FRI

下面的表达式
0 15 10   * 6L 2002-2005
将在2002年到2005年的每个月的最后一个星期五上午10点15分执行作业。

你不可能用SimpleTrigger来做这些事情。你可以用两者之中的任何一个,但哪个跟合适则取决于你的调度需要。
更多详细介绍参考此处:

关于cronExpression的介绍:

字段 允许值 允许的特殊字符
0-59 , - * /
0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - *   / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - *   / L C #
年(可选) 留空, 1970-2099 , - * /

如上面的表达式所示:

“*”字符被用来指定所有的值。如:”*“在分钟的字段域里表示“每分钟”。

“-”字符被用来指定一个范围。如:“10-12”在小时域意味着“10点、11点、12点”。

“,”字符被用来指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”.

“?”字符只在日期域和星期域中使用。它被用来指定“非明确的值”。当你需要通过在这两个域中的一个来指定一些东西的时候,它是有用的。看下面的例子你就会明白。

“L”字符指定在月或者星期中的某天(最后一天)。即“Last ”的缩写。但是在星期和月中“L”表示不同的意思,如:在月子段中“L”指月份的最后一天-1月31日,2月28日,如果在星期字段中则简单的表示为“7”或者“SAT”。如果在星期字段中在某个value值得后面,则表示“某月的最后一个星期value”,如“6L”表示某月的最后一个星期五。

“W”字符只能用在月份字段中,该字段指定了离指定日期最近的那个星期日。

“#”字符只能用在星期字段,该字段指定了第几个星期value在某月中

表达式 意义
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

每天早上6点

0 6 * * *

每两个小时

0 */2 * * *
晚上11点到早上8点之间每两个小时,早上八点

0 23-7/2,8 * * *

每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点

0 11 4 * 1-3
1月1日早上4点

0 4 1 1 *

定时批处理作业是J2EE企业应用里很重要的一环,用来在晚间进行财务挂账,数据转存,新闻联播等等操作。

而在Spring里,已经很好的集成了Quartz,简单到像配cron一样,在xml文件里面配一下时间就可以自动执行,不需要写一行代码。Spring对Quartz大刀阔斧的简化堪称范例,Quartz项目组也许可以学习一下。

上面这段配置文件规定了在早上6点和晚上8点执行financeDAO对象的confirmOrder()方法.