JNI原理及常用方法概述
1.1 JNI(Java Native Interface)
提供一种Java字节码调用C/C++的解决方案,JNI描述的是一种技术。
1.2 NDK(Native Development Kit)
Android NDK 是一组允许您将 C 或 C++(“原生代码”)嵌入到 Android 应用中的工具,NDK描述的是工具集。 能够在 Android 应用中使用原生代码对于想执行以下一项或多项操作的开发者特别有用:
- 在平台之间移植其应用。
- 重复使用现有库,或者提供其自己的库供重复使用。
- 在某些情况下提高性能,特别是像游戏这种计算密集型应用。
1.3 JNI方法注册
1.3.1静态注册
当Java层调用navtie函数时,会在JNI库中根据函数名查找对应的JNI函数。如果没找到,会报错。如果找到了,则会在native函数与JNI函数之间建立关联关系,其实就是保存JNI函数的函数指针。下次再调用native函数,就可以直接使用这个函数指针。
- JNI函数名格式(需将”.”改为”_”):
Java_ + 包名(com.example.auto.jnitest)+ 类名(MainActivity) + 函数名(stringFromJNI)
- 静态方法的缺点:
- 要求JNI函数的名字必须遵循JNI规范的命名格式;
- 名字冗长,容易出错;
- 初次调用会根据函数名去搜索JNI中对应的函数,会影响执行效率;
- 需要编译所有声明了native函数的Java类,每个所生成的class文件都要用javah工具生成一个头文件;
1.3.2动态注册
通过提供一个函数映射表,注册给JVM虚拟机,这样JVM就可以用函数映射表来调用相应的函数,就不必通过函数名来查找需要调用的函数。
- Java与JNI通过JNINativeMethod的结构来建立函数映射表,它在jni.h头文件中定义,其结构内容如下:
typedef struct {const char* name;const char* signature;void* fnPtr;
} JNINativeMethod;
- 创建映射表后,调用RegisterNatives函数将映射表注册给JVM;
- 当Java层通过System.loadLibrary加载JNI库时,会在库中查JNI_OnLoad函数。可将JNI_OnLoad视为JNI库的入口函数,需要在这里完成所有函数映射和动态注册工作,及其他一些初始化工作。
1.4 数据类型转换
1.4.1 基础数据类型转换
1.4.2 引用数据类型转换
除了Class、String、Throwable和基本数据类型的数组外,其余所有Java对象的数据类型在JNI中都用jobject表示。Java中的String也是引用类型,但是由于使用频率较高,所以在JNI中单独创建了一个jstring类型。
- 引用类型不能直接在 Native 层使用,需要根据 JNI 函数进行类型的转化后,才能使用;
- 多维数组(含二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值;
例如,二维整型数组就是指向一位数组的数组,其声明使用方式如下:
//获得一维数组的类引用,即jintArray类型 jclass intArrayClass = env->FindClass("[I"); //构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为length,类型为 jsizejobjectArray obejctIntArray = env->NewObjectArray(length ,intArrayClass , NULL);
1.4.3 JNI函数签名信息
由于Java支持函数重载,因此仅仅根据函数名是没法找到对应的JNI函数。为了解决这个问题,JNI将参数类型和返回值类型作为函数的签名信息。
-
JNI规范定义的函数签名信息格式:
(参数1类型字符…)返回值类型字符 -
函数签名例子:
-
JNI常用的数据类型及对应字符:
1.4.4 JNIEnv介绍
- JNIEnv概念 :
JNIEnv是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境。通过JNIEnv可以调用到一系列JNI系统函数。 - JNIEnv线程相关性:
每个线程中都有一个 JNIEnv 指针。JNIEnv只在其所在线程有效, 它不能在线程之间进行传递。
注意:在C++创建的子线程中获取JNIEnv,要通过调用JavaVM的AttachCurrentThread函数获得。在子线程退出时,要调用JavaVM的DetachCurrentThread函数来释放对应的资源,否则会出错。
- JNIEnv 作用:
- 访问Java成员变量和成员方法;
- 调用Java构造方法创建Java对象等。
1.5 JNI编译
1.5.1 ndkBuild
使用ndk-build编译生成so文件
1.5.2 Cmake编译
CMake 则是一个跨平台的编译工具,它并不会直接编译出对象,而是根据自定义的语言规则(CMakeLists.txt)生成 对应 makefile 或 project 文件,然后再调用底层的编译, 在Android Studio 2.2 之后支持Cmake编译。
-
add_library 指令
语法:add_library(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] [source])
将一组源文件 source 编译出一个库文件,并保存为 libname.so (lib 前缀是生成文件时 CMake自动添加上去的)。其中有三种库文件类型,不写的话,默认为 STATIC;
- SHARED: 表示动态库,可以在(Java)代码中使用 System.loadLibrary(name) 动态调用;
- STATIC: 表示静态库,集成到代码中会在编译时调用;
- MODULE: 只有在使用 dyId 的系统有效,如果不支持 dyId,则被当作 SHARED 对待;
- EXCLUDE_FROM_ALL: 表示这个库不被默认构建,除非其他组件依赖或手工构建;
#将compress.c 编译成 libcompress.so 的共享库
add_library(compress SHARED compress.c)
- target_link_libraries 指令
语法:target_link_libraries(target library <debug | optimized> library2…)
这个指令可以用来为 target 添加需要的链接的共享库,同样也可以用于为自己编写的共享库添加共享库链接。如:
#指定 compress 工程需要用到 libjpeg 库和 log 库
target_link_libraries(compress libjpeg ${log-lib})
- find_library 指令
语法:find_library( name1 path1 path2 …)
VAR 变量表示找到的库全路径,包含库文件名 。例如:
find_library(libX X11 /usr/lib)
find_library(log-lib log) #路径为空,应该是查找系统环境变量路径
Android NDK 开发:CMake 使用
1.5.3 Abi架构
ABI(Application binary interface)应用程序二进制接口。不同的CPU 与指令集的每种组合都有定义的 ABI (应用程序二进制接口),一段程序只有遵循这个接口规范才能在该 CPU 上运行,所以同样的程序代码为了兼容多个不同的CPU,需要为不同的 ABI 构建不同的库文件。当然对于CPU来说,不同的架构并不意味着一定互不兼容。
- armeabi设备只兼容armeabi;
- armeabi-v7a设备兼容armeabi-v7a、armeabi;
- arm64-v8a设备兼容arm64-v8a、armeabi-v7a、armeabi;
- X86设备兼容X86、armeabi;
- X86_64设备兼容X86_64、X86、armeabi;
- mips64设备兼容mips64、mips;
- mips只兼容mips;
根据以上的兼容总结,我们还可以得到一些规律:
- armeabi的SO文件基本上可以说是万金油,它能运行在除了mips和mips64的设备上,但在非armeabi设备上运行性能还是有所损耗;
- 64位的CPU架构总能向下兼容其对应的32位指令集,如:x86_64兼容X86,arm64-v8a兼容armeabi-v7a,mips64兼容mips;
1.5.4 Jni技术实现原理
我们知道cpu只认得 “0101101” 类似这种符号, C、C++ 这些代码最终都得通过编译、汇编成二进制代码,cpu才能识别。而Java比C、C++又多了一层虚拟机,过程也复杂许多。Java代码经过编译成class文件、虚拟机装载等步骤最终在虚拟机中执行。class文件里面就是一个结构复杂的表,而最终告诉虚拟机怎么执行的就靠里面的字节码说明。
Java虚拟机在执行的时候,可以采用解释执行和编译执行的方式执行,但最终都是转化为机器码执行。
Java虚拟机运行时的数据区,包括方法区、虚拟机栈、堆、程序计数器、本地方法栈。
问题来了,按我目前的理解,如果是解释执行,那么方法区中应该存的是字节码,那执行的时候,通过JNI 动态装载的c、c++库,放哪去?怎么执行?这个问题,搜索了许多标题写着”JNI实现原理”的文章,都是抄来抄去,并没去探究如何实现的,只是讲了java如何使用JNI。好吧,就从如何使用JNI开始。
1.6 JNI的简单实现
参考文章:《Java JNI简单实现》、《JAVA基础之理解JNI原理》
假设当前的目录结构如下:
-
| - maniu| Test.java
1.首先编写java文件
Test.java
package maniu;
public class Test{static{System.loadLibrary("bridge");}public native int nativeAdd(int x,int y);public static void main(String[] args){Test obj = new Test();System.out.printf("%d\n",obj.nativeAdd(2012,3));}
}
代码很简单,这里声明了nativeAdd(int x,inty)
的方法,执行的时候简单的打出执行的结果。另外这里调用API加载名称叫bridge
的库,接下来就来实现这个库。
2.生成JNI调用需要的头文件
javac maniu/Test.java
javah -jni maniu.Test
现在目录结构是这样的:
-
| - maniu| Test.java| Test.class
| - maniu_Test.h
maniu_Test.h头文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class maniu_Test */#ifndef _Included_maniu_Test
#define _Included_maniu_Test
#ifdef __cplusplus
extern "C" {
#endif
/** Class: maniu_Test* Method: nativeAdd* Signature: (II)I*/
JNIEXPORT jint JNICALL Java_maniu_Test_nativeAdd(JNIEnv *, jobject, jint, jint);#ifdef __cplusplus
}
#endif
1.6.1 生成的代码阅读
经常会见到__cplusplus关键字,比如下面的代码:
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_maniu_Test_nativeAdd(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
这里面,两种关键字,都是为了实现C++与C兼容的,extern “C”是用来在C++程序中声明或定义一个C的符号,比如:
extern “C” {int func(int);int var;}
上面的代码,C++编译器会将在extern “C”的大括号内部的代码当做C语言来处理。
由于C和C++毕竟是不同的,为了实现某个程序在C和C++中都是兼容的,如果定义两套头文件,未免太过麻烦,所以就有了__cplusplus的出现,这个是在C++中特有的,__cplusplus其实就是C++,也就有了上面第一段代码的使用,如果这段代码是在C++文件中出现,那么经过编译后,该段代码就变成了:
/**********C++文件中条件编译后结果***************/
extern "C" {
JNIEXPORT jint JNICALL Java_maniu_Test_nativeAdd(JNIEnv *, jobject, jint, jint);
}
而在C文件中,经过条件编译,该段代码变成了:
/**********C文件中条件编译后结果*************/
JNIEXPORT jint JNICALL Java_maniu_Test_nativeAdd(JNIEnv *, jobject, jint, jint);
3.native方法的实现
这里新增bridge.c
文件来实现之前声明的native方法,目录结构如下:
-
| - maniu| Test.java| Test.class
| - maniu_Test.h
| - bridge.c
bridge.c的内容如下:
#include "maniu_Test.h"JNIEXPORT jint JNICALL Java_maniu_Test_nativeAdd
(JNIEnv * env, jobject obj, jint x, jint y){return x+y;
}
这里的实现只是简单的把两个参数相加,然后返回。
4.生成动态链接库
gcc -shared -o dll_demo.dll bridge.c
最后需要注意一点的是 -o
选项,我们在java代码中调用的是System.loadLibrary("xxx")
,那么生成的动态链接库的名称就必须是libxxx.so
的形式(这里指Linux环境),否则在执行java代码的时候,就会报 java.lang.UnsatisfiedLinkError: no XXX in java.library.path
的错误!也就是说找不到这个库,我在这里被坑了一小段时间。
好了,现在的目录结构如下:
-
| - maniu| Test.java| Test.class
| - maniu_Test.h
| - bridge.c
| - libbridge.so
5.执行代码验证结果
java -Djava.library.path=. maniu.Test
2015
ok,Java 使用JNI的最简单的例子就完成了。
1.6.2 JNI实现原理
那么,我们的问题还没解决,刚刚生成的动态链接库”libbridge.so”是怎么装进内存的?native方法怎么调用?跟普通的方法调用有什么区别吗?
我们把Test.java改改,增加普通的方法”int add(int x,int y)”
Test.java
package maniu;
public class Test{static{System.loadLibrary("bridge");}public native int nativeAdd(int x,int y);public int add(int x,int y){return x+y;}public static void main(String[] args){Test obj = new Test();System.out.printf("%d\n",obj.nativeAdd(2012,3));System.out.printf("%d\n",obj.add(2012,3));}
}
我们把它编译成class文件,再看看class文件中,native方法和普通方法有何区别:
javac maniu/Test.java
javap -verbose maniu.Test
解析后,”nativeAdd”和”add”两个方法的结果如下:
public native int nativeAdd(int, int);flags: ACC_PUBLIC, ACC_NATIVEpublic int add(int, int);flags: ACC_PUBLICCode:stack=2, locals=3, args_size=30: iload_1 1: iload_2 2: iadd 3: ireturn LineNumberTable:line 8: 0
可见,普通的“add”方法是直接把字节码放到code属性表中,而native方法,与普通的方法通过一个标志“ACC_NATIVE”区分开来。java在执行普通的方法调用的时候,可以通过找方法表,再找到相应的code属性表,最终解释执行代码,那么,对于native方法,在class文件中,并没有体现native代码在哪里,只有一个“ACC_NATIVE”的标识,那么在执行的时候改怎么找到动态链接库的代码呢?
只能从System.loadLibrary()
入手了!
相关文章:
![](https://img-blog.csdnimg.cn/img_convert/fb726af0e444019feb1268123d3d68c9.webp?x-oss-process=image/format,png)
JNI原理及常用方法概述
1.1 JNI(Java Native Interface) 提供一种Java字节码调用C/C的解决方案,JNI描述的是一种技术。 1.2 NDK(Native Development Kit) Android NDK 是一组允许您将 C 或 C(“原生代码”)嵌入到 Android 应用中的工具,NDK描述的是工具集…...
![](https://img-blog.csdnimg.cn/05a6b930e9b74990a89e1f3936064a8c.png)
【Docker】之docker-compose的介绍与命令的使用
🍁博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 文章目录docker-compose简介docker-compose基础…...
![](https://img-blog.csdnimg.cn/9431052ba024472f9901b1e774aac902.png#pic_center)
水果新鲜程度检测系统(UI界面+YOLOv5+训练数据集)
摘要:水果新鲜程度检测软件用于检测水果新鲜程度,利用深度学习技术识别腐败或损坏的水果,以辅助挑拣出新鲜水果,支持实时在线检测。本文详细介绍水果新鲜程度检测系统,在介绍算法原理的同时,给出Python的实…...
![](https://www.ngui.cc/images/no-images.jpg)
flask多并发
多线程 flask默认使用多进程处理请求,因此,是支持并发的。比如两个调用a.html和b.html, 请求a.html未运行完成,在浏览访问b.html不会阻塞。开两个不同浏览器,分别请求请求运行时间较长的a.html也不阻塞。只要不用一个…...
![](https://img-blog.csdnimg.cn/img_convert/fa4cd871faaa4b938b3dac5bf7973a12.jpeg)
我用Python django开发了一个商城系统,已开源,求关注!
起始 2022年我用django开发了一个商城的第三方包,起名为:django-happy-shop。当时纯粹是利用业余时间来开发和维护这个包,想法也比较简单,Python语言做web可能用的人比较少,不一定有多少人去关注,就当是一个…...
![](https://img-blog.csdnimg.cn/58a03d4d7be14fbf99e7c26938fc700f.png)
大数据项目之数仓相关知识
第1章 数据仓库概念 数据仓库(DW): 为企业指定决策,提供数据支持的,帮助企业,改进业务流程,提高产品质量等。 DW的输入数据通常包括:业务数据,用户行为数据和爬虫数据等 ODS: 数据…...
![](https://img-blog.csdnimg.cn/f5d9ea1eaf0b46b99818aa9471b2ee10.jpeg)
RK3588平台开发系列讲解(视频篇)RTP H264 码流打包详解
平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、单 NALU 封包方式二、组合封包方式三、分片封包方式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 H264 码流是放在 RTP 的有效载荷部分的。因此有效载荷前面的 RTP 头部跟码流本身是没有关系的,所以我…...
![](https://www.ngui.cc/images/no-images.jpg)
realloc的补充 柔性数组
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…...
![](https://img-blog.csdnimg.cn/4632463a72104169838246cf21712270.png)
【C语言】柔性数组
柔性数组1. 柔性数组介绍2. 柔性数组特点3. 用例3.1 代码一:3.2 代码二:4. 柔性数组优势:1. 柔性数组介绍 也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。 C99 中,…...
![](https://img-blog.csdnimg.cn/img_convert/c6588e81487da374f3ce69ddffacbe4c.png)
【Linux】权限详解
前言首先我们先来看一下权限的概念:在多用户计算机系统的管理中,权限(privilege)是指某个特定的用户具有特定的系统资源使用权力,像是文件夹,特定系统指令的使用或存储量的限制。通常,系统管理员…...
![](https://img-blog.csdnimg.cn/img_convert/048293c67da93a9dafa3596fd8060e28.png)
Android 之 打开相机 打开相册
Android 之 打开系统摄像头拍照 打开系统相册,并展示1,清单文件 AndroidManifest.xml<uses-permission android:name"android.permission.INTERNET" /><!--文件读取权限--><uses-permission android:name"android.permiss…...
![](https://img-blog.csdnimg.cn/img_convert/b572dd1bd2640e00620327890f6002da.gif)
C语言数据结构初阶(8)----栈与队列OJ题
CSDN的uu们,大家好。这里是C语言数据结构的第八讲。 目标:前路坎坷,披荆斩棘,扶摇直上。 博客主页: 姬如祎 收录专栏:数据结构与算法栈与队列的知识点我➡➡队列相关点我➡➡栈相关2. 用栈实现队列原题链接…...
![](https://img-blog.csdnimg.cn/2304311dc8ef46d2972cccbe8ed3769a.png)
JavaScript——原型对象
JavaScript——原型对象专题 文章目录JavaScript——原型对象专题1. 原型对象2. 原型对象的this指向3. 案例4. constructor属性5. 对象原型6. 总结7. 原型继承8. 原型链由先前的学习可知,构造函数实例创建的对象彼此独立、互不影响,很好的体现了面向对象…...
![](https://img-blog.csdnimg.cn/img_convert/7a818b118d6e747f4db77f71a50dc446.png)
网络安全 2023 年为什么如此吃香?事实原来是这样....
前言由于我国网络安全起步晚,所以现在网络安全工程师十分紧缺。俗话说:没有网络安全就没有国家安全为什么选择网络安全?十四五发展规划建议明确提出建设网络强国,全面加强网络安全保障体系和能力建设,加强网络文明建设,…...
![](https://img-blog.csdnimg.cn/img_convert/e38aa3a3631587c9d80e145027721cbe.gif)
(源码篇02)webpack5中的事件调度系统和NormalModuleFactary核心逻辑
1. 书接上回,从 this.factorizeQueue.add(options, callback); 开始 不是很清楚上下文的兄弟,可以去看下我之前写的 (源码篇01)浅析webpack5中Compiler中重要的hook调用过程。 此文比较干,各位读者开始阅读前…...
![](https://www.ngui.cc/images/no-images.jpg)
Vue2.x源码:new Vue()做了啥?
vue源码版本vue2.5.2 new Vue()做了啥? new Vue()会执行_init方法,而_init方法在initMixin函数中定义。 src/core/instance/index.js文件中定义了Vue function Vue (options) {this._init(options) }initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycl…...
![](https://img-blog.csdnimg.cn/6df947fa2672441fbeffad7ab236209f.gif)
WinForm | C# 弹出简易的消息提示框 (仿Android Toast消息提示)
ApeForms Toast消息提示 文章目录ApeForms Toast消息提示前言方法原型及参数释义消息驻留延时消息弹出模式队列模式抢占模式复用模式UI库安装与使用获取示例源码前言 在使用手机的时候经常会见到屏幕的中下方会弹出消息提示框,它就是Toast,以下是百度百…...
![](https://img-blog.csdnimg.cn/14521abb4a2f4545a40112f010a3f449.png)
1、DRF实战总结:DRF特点、序列化与RESTful API规范
Django这种基于MVC开发模式的传统框架,非常适合开发基于PC的传统网站,因为它同时包括了后端的开发(逻辑层、数据库层) 和前端的开发(如模板语言、样式)。现代网络应用Web APP或大型网站一般是一个后台,然后对应各种客户端(iOS, android, 浏览…...
![](https://www.ngui.cc/images/no-images.jpg)
SIP协议及其简单介绍
SIP协议及其简单介绍概述流程SIP流程两台设备建立会话原理使用场景概述 SIP(Session Initiation Protocol,会话初始化协议)是一个应用层协议,用于在互联网上创建、修改和终止多媒体会话。SIP是一个客户端/服务器协议,…...
![](https://img-blog.csdnimg.cn/img_convert/24fc9a2d3328a472b3e32ec4408e75e8.png)
安全防御第四天:防病毒网关
一、恶意软件1.按照传播方式分类(1)病毒病毒是一种基于硬件和操作系统的程序,具有感染和破坏能力,这与病毒程序的结构有关。病毒攻击的宿主程序是病毒的栖身地,它是病毒传播的目的地,又是下一次感染的出发点…...
![](https://img-blog.csdnimg.cn/img_convert/b10572865d80068afc57faffed987b12.png)
Postman接口与压力测试实例
Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。它提供功能强大的 Web API & HTTP 请求调试。 1、环境变量和全局变量设置 环境变量可以使用在以下地方: URLURL paramsHeader valuesform-data/url-encoded valuesRaw body contentHelper fi…...
![](https://www.ngui.cc/images/no-images.jpg)
TCP/IP socket
## TCP Socket 收发缓冲区: 每个socket在linux内核中都有一个发送缓冲区和一个接收缓冲区。 只要对端将数据发送过来,linux内核TCP/IP协议栈就会负责将数据缓存到socket对应的接收缓冲区中,无论是否调用recv。 recv()所做的工作,只是把内核缓…...
![](https://img-blog.csdnimg.cn/img_convert/8cae93d84c877e2fdd96a102d02c4bbd.png)
“工作三年,跳槽要求涨薪50%”,合理吗?
如果问在TI行业涨工资最快的方式是什么?回答最多的一定是:跳槽!前段时间,知乎上这样一条帖子引发了不少IT圈子的朋友的讨论 ,有网友提问 “程序员跳槽要求涨薪50%过分吗?”截图来源于知乎,如侵删…...
![](https://www.ngui.cc/images/no-images.jpg)
Vue学习计划九:了解Vue动画效果以及过渡动画和动态组件的使用方法
Vue.js 是一个流行的 JavaScript 框架,它提供了很多工具和功能,可以帮助开发人员创建动态、交互式的 Web 应用程序。其中之一就是动画效果,Vue.js 提供了一系列的 API 和指令,使得添加动画效果变得非常容易。 在 Vue.js 中&#…...
![](https://img-blog.csdnimg.cn/img_convert/d36bb1d155d440a4b5b461108e4087ae.png)
【Linux】进程理解与学习Ⅲ-环境变量
环境:centos7.6,腾讯云服务器Linux文章都放在了专栏:【Linux】欢迎支持订阅🌹相关文章推荐:【Linux】冯.诺依曼体系结构与操作系统【Linux】进程理解与学习Ⅰ-进程概念浅谈Linux下的shell--BASH【Linux】进程理解与学习…...
![](https://img-blog.csdnimg.cn/e50ee4e5b0a5455194b0431165d409f5.png)
【三】一起算法---栈:STL stack、手写栈、单调栈
纸上得来终觉浅,绝知此事要躬行。大家好!我是霜淮子,欢迎订阅我的专栏《算法系列》。 学习经典算法和经典代码,建立算法思维;大量编码让代码成为我们大脑的一部分。 ⭐️已更系列 1、基础数据结构 1.1、链表➡传送门 1…...
![](https://img-blog.csdnimg.cn/1794c0004d274ed893e2c76f5658e912.png)
电路设计的一些概念
锁存器的产生 论述1 (转)时序电路,生成触发器,触发器是有使能端的,使能端无效时数据不变,这是触发器的特性。 组合逻辑,由于数据要保持不变,只能通过锁存器来保存。 第一个代码,由于是时序逻…...
![](https://img-blog.csdnimg.cn/69772a93ecd44095ae11aa2560af5847.png)
【Linux】Linux下权限的理解
前言:在之前我们已经对基本的指令进行了深入的学习,接下来我将带领大家学习的是关于权限的相关问题。在之前,我们一直是使用的【root】用户,即为“超级用户”,通过对权限的学习之后,我们就会慢慢的切换到普…...
![](https://img-blog.csdnimg.cn/0cb885c99cc0484499fbef97274ba639.png)
Prometheus监控实战系列十七:探针监控
目前对于应用程序的监控主要有两种方式,一种被称为白盒监控,它通过获取目标的内部信息指标,来监控目标的状态情况,我们前面介绍的主机监控、容器监控都属于此类监控。另一种则是“黑盒监控”,它指在程序外部通过探针的…...
![](https://www.ngui.cc/images/no-images.jpg)
题目:JPA的懒加载失效是什么情况?
题目:JPA的懒加载失效是什么情况?Q1:什么是JPA的懒加载?Q2:JPA的懒加载会在什么情况下失效?Q3:如何避免JPA的懒加载失效?前言:在使用JPA进行数据库操作时,懒加…...
![](http://hi.csdn.net/attachment/201201/1/0_1325387492E3p4.gif)
站长推荐/互联网营销的方式有哪些
1.将分区信息写到硬盘的第一个设备节点的MBR结构中的分区表;2.格式化分区到指定的文件系统类型。MBR中存放分区表的位置在446-509,占用了64字节,MBR结构只支持4个主分区,所以有4个16字节的区域,先简要说明一下MBR的分区…...
![](/images/no-images.jpg)
香港外贸网站建设/个人推广app的妙招
find命令简介: 实时、精确、支持众多查找标准遍历指定目录中的所有文件完成查找,速度慢;1.命令格式:locate filename 直接跟需要查找的文件 eg locate passwd 系统文件数据库中所有包含passwd的文件。find 查找路径…...
![](/images/no-images.jpg)
wordpress设置背景/合肥做网站哪家好
忙,还有两周多就要上线了,可是项目也就开始两周多。我现在估计已经快疯了。忙的时候,觉得自己实在是有心无力。如果说blog是一块镜子,那么我希望逃避。夜深人静的时候,我都不逃避,但是我已经累的倒下了&…...
![](/images/no-images.jpg)
凡客v十商城还在吗/seo诊断专家
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0; 思路:遍历查找非整数字符,第一个字符串位置进行判断, 采用-‘0’算出整数*10的多少次方;…...
![](/images/no-images.jpg)
做购物商城类网站需要/有没有推广app的平台
这篇文章是转载的,为了便于查找一些指令,贴在这里。 转自:http://blog.csdn.net/canfengxiliu/article/details/20144119 --------------------- 声明 : 文章是看<<Android软件安全与逆向分析>> 的所写笔记。 Dalvik指…...
![](/images/no-images.jpg)
龙岗住房建设局网站/无锡百度竞价推广
JSON&XML: JSON----- //英译 Serialization:序列化 perform:执行 segue:继续 IOS5后 NSJSONSerialization解析 解析JSON SBJSON JSONKit touchJson的第三方库 性能:NSJSONSerial…...