好像快一年没更新了,也不知道写啥
阅读视图
麒麟系统编译jcef
获取系统
可以从优麒麟的官网获取最新版22.04、20.04和V10的安装包,我这里用的是一个老版本。
https://www.ubuntukylin.com/downloads/
安装过程这里就省略了,基本上按照提示来就行了。
下载JCEF代码
jcef项目在Bitbucket上,地址如下:
https://bitbucket.org/chromiumembedded/java-cef/src/master/
现在jcef在Github也有代码了,但是提issue的话最好是去Bitbucket上:
https://github.com/chromiumembedded/java-cef
sudo apt-get install git #麒麟系统有的版本并没有git需要先手动安装一下
git clone https://github.com/chromiumembedded/java-cef.git #下载源代码
编译JCEF
其实打开代码里的CMakeLists.txt
可以看到编译的要求和基本的步骤,可以看到最新版的jcef100要求的CMake的最低版本是3.19,但是目前麒麟系统能下载到的最新版为3.5.1,不符合要求。这里的话有两种方法,一种是下载最新版CMake源码编译安装,另一种是编译一个老版本的jcef。
我选的是后一种方法,毕竟,用麒麟系统的人也不是那么需要最新版的代码。
查看git log可以发现,在2021年12月14日,jcef更新了MakeFile,而在此之前的jcef95要求的CMake版本是2.8。
使用git reset退回到CEF version 95.7.14+g9f72f35+chromium-95.0.4638.69这个版本。
git reset --hard ae6912a705e6a2a60f0f156fcc2e8c03bf8285c4
我们还需要安装build-essential
这个包。
sudo apt-get install build-essential
麒麟系统自带了JDK 1.8,但是并没配置Java Home,需要我们手动配置一下
vi /etc/profile
#在末尾添加
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
#保存退出
#退出以后执行
source /etc/profile
然后就可以开始编译了:
cd /java-cef/src #到代码路径下src文件夹下
mkdir jcef_build && cd jcef_build
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ..
make -j4
如果你的网络条件比较好的话,基本就可以顺利编译完成,但是如果不那么理想的话,可以手动去http://opensource.spotify.com/cefbuilds/下载一下编译所需要的文件,需要下载的是95版本Linux 64的包。将下载好的包放到java-cef/src/third_party/cef
路径下。
使用如下指令编译所需的Java Class文件。
cd /java-cef/src/tools
./compile.sh linux64
测试编译结果
cd /java-cef/src/tools
./run.sh linux64 Debug detailed
运行效果如图
打包
测试正常后可以使用打包工具进行打包,毕竟不可能每台机器都这样编译一通。
cd /java-cef/src/tools
./make_distrib.sh linux64
打包的文件在/out
路径下。
最后
其实,官方也知道jcef这个编译是个大坑,没个半天功夫根本搞不定,于是官方把jcef运行需要的包和可执行文件上传到了Maven,方便了太多。但是这个可执行文件在Windows下测试可行,而麒麟系统下却报错,有点可惜。
Windows下的maven dependency:
<dependency>
<groupId>me.friwi</groupId>
<artifactId>jcefmaven</artifactId>
<version>95.7.14.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/me.friwi/jcef-natives-windows-amd64 -->
<dependency>
<groupId>me.friwi</groupId>
<artifactId>jcef-natives-windows-amd64</artifactId>
<version>jcef-544024e+cef-95.7.14+g9f72f35+chromium-95.0.4638.69</version>
</dependency>
顺便提一嘴,这个native包用阿里的源下载不下来,后来适用华为的源下下来的。
Linux IO多路复用分析(Select、Poll和Epoll)
前段时间被迫把一坨没人维护代码中的Select机制换成了Epoll,借此机会梳理一下Select、Poll和Epoll的原理。
I/O多路复用:
I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
Select:
函数原型和使用:
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)
void FD_ZERO(fd_set *fdset);//清空集合
void FD_SET(int fd, fd_set *fdset);//将一个给定的文件描述符加入集合之中
void FD_CLR(int fd, fd_set *fdset);//将一个给定的文件描述符从集合中删除
int FD_ISSET(int fd, fd_set *fdset);// 检查集合中指定的文件描述符是否可以读写
缺点:
- 每次调用select,都需要把fd集合从用户态拷贝到内核态,也需要在内核遍历传递进来的所有fd,开销过大
- select支持的文件描述符数量过小,默认是1024,且调大需要重新编译系统内核
Poll:
函数原型和使用:
# include <poll.h>
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);
/*Poll结构体*/
struct pollfd {
int fd;/* 文件描述符 */
short events;/* 等待的事件 */
short revents;/* 实际发生了的事件 */
};
缺点:
- 只解决了select描述符上限的问题,没解决效率问题。
Epoll:
epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。
函数原型和使用:
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
缺点:
- 使用较为复杂
简单的总结:
对比 | Select | Poll | Epoll |
---|---|---|---|
机制 | 轮询 | 轮询 | 通知 |
默认FD上限 | 1024 | 无上限 | 无上限 |
效率 | 低 | 低 | 高 |
参考资料:
https://www.cnblogs.com/anker/p/3265058.html
https://blog.csdn.net/qq_39612543/article/details/121963681
Java使用JNA访问本地库
JNA(Java Native Access )是一个基于JNI的开源库,能有效提高Java访问调用本地库的效率。
官方介绍
JNA 为 Java 程序提供了对本机共享库的轻松访问,而无需编写除 Java 代码之外的任何内容 - 不需要 JNI 或本机代码。此功能可与Windows的Platform /Invoke和Python的ctype相媲美。
JNA 允许您使用自然 Java 方法调用直接调用本机函数。Java 调用看起来就像本机代码中的调用一样。大多数呼叫不需要特殊处理或配置;不需要样板或生成的代码。
JNA 使用一个小型 JNI 库存根来动态调用本机代码。开发人员使用 Java 接口来描述目标本机库中的函数和结构。这使得利用本机平台功能变得非常容易,而不会产生为多个平台配置和构建 JNI 代码的高开销。阅读此更深入的描述。
使用方法
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface JnaDemo extends Library {
JnaDemo INSTANCE = (JnaDemo) Native.loadLibrary("demo",JnaDemo.class);
//demo处写需要调用的动态库名字,不写.so或.dll
...
//此处写需要调用的库函数,注意不同类型的对应关系
}
注意事项:
- 如果同时加载多个动态库,不要出现同名的函数,否则可能会出现致命错误。
- C++与Java类型的对应关系一定要写对,否则也会出现致命错误。
待续