Java JVM、JNI、Native Function Interface、Create New Process Native Function API Analysis

目录

1. JAVA JVM
2. Java JNI: Java Native Interface
3. Java Create New Process Native Function API Analysis In Linux
4. Java Create New Process Native Function API Analysis In Windows

 

1. JAVA JVM

0x1: JVM架构简介

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的
Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够"一次编译,到处运行"的原因

JVM的设计目标是提供一个基于抽象规格描述的计算机模型,为解释程序开发人员提很好的灵活性,同时也确保Java代码可在符合该规范的任何系统上运行。JVM对其实现的某些方面给出了具体的定义

1. Java可执行代码,即字节码(Bytecode)格式,包括1) 操作码的语法和数值2) 操作数的语法和数值3) 标识符的数值表示方式4) Java类文件中的Java对象、常量缓冲池在JVM的存储映象
//这些定义为JVM解释器开发人员提供了所需的信息和开发环境 
2. JVM指令系统
3. JVM寄存器
4. JVM栈结构
5. JVM碎片回收堆
6. JVM存储区

JVM是JAVA的核心和基础,在JAVA编译器和OS平台之间的虚拟处理器。它是一种基于下层的操作系统和硬件平台并利用软件方法来实现的抽象的计算机,可以在上面执行JAVA的字节码程序
JAVA编译器只需面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译器,编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行

//JVM执行程序的过程 
1. 加载.class文件
2. 管理并分配内存
3. 执行垃圾收集

JRE(Java Runtime Environment)包含JVM的java程序的运行环境,即JVM是整个JRE的一部分
JVM是Java程序运行的容器,但是他同时也是操作系统的一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间
JVM在整个JDK中处于最底层,负责与操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机。操作系统装入JVM是通过JDK中Java.exe来完成,通过下面4步来完成JVM环境(windows)

1. 创建JVM装载环境和配置
2. 装载JVM.dll
3. 初始化JVM.dll,并挂接到JNIENV(JNI调用接口)实例
4. 调用JNIEnv实例装载并处理class类 

Relevant Link:

http://baike.baidu.com/view/160708.htm
http://zh.wikipedia.org/wiki/Java%E8%99%9A%E6%8B%9F%E6%9C%BA
http://en.wikipedia.org/wiki/Java_virtual_machine

 

2. Java JNI: Java Native Interface

0x1: 本地方法栈(Native Method Stacks)

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用很类似,区别是

1. 虚拟机栈为虚拟机执行Java方法(字节码)服务
2. 本地方法栈为虚拟机使用到的Native方法服务

虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(例如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一,与虚拟机一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常

0x2: Java本地接口

Java本地接口(JNI)是一个"编程框架"使得运行在Java虚拟机上的Java程序调用或者被调用特定于本机硬件与操作系统的用其它语言(C、C++或汇编语言等)编写的程序

1. JNI允许用本地代码(和具体操作系统平台相关的代码,例如用glibc编译、和用CRT编译的平台相关代码)来解决纯粹用Java编程不能解决的平台相关的特性。也用于改造已存在的其它语言写的应用程序,供Java程序访问。许多使用了JNI的标准库提供了文件I/O与其它功能。标准库中性能敏感或平台敏感的API实现允许所有Java应用程序安全且平台独立地访问这些功能2. JNI框架使得本地方法可以访问Java对象,就如同Java程序访问这些本地对象。本地方法可以创建Java对象,然后检查、使用这些对象执行任务。本地方法也可以检查并使用由Java程序创建的对象3. Java开发人员称JNI为逃生门("escape hatch"),因为JINI允许增加标准Java API不能提供的功能。也可以用于时间关键的计算或者如解复杂数学方程,因为本地方法的运算比JVM更快。也可以在安卓上重用已存在的C/C++编写的库

0x3: 使用JNI存在的问题

1. 使用JNI的精细的错误会使JVM不稳定,并且难以再现与调试 2. 仅有应用程序与signed applet可以调用JNI3. 依赖于JNI的应用程序失去了Java的平台移植性(部分解决之道是对每一平台写专门的JNI代码,然后Java检测操作系统并载入当前的JNI代码)4. JNI框架对本地端执行代码分配的非JVM资源,不提供任何自动的垃圾收集(例如C/C++代码)。因此,本地端代码负责释放任何在本地获取的资源5. Linux与Solaris平台,如果本地代码登记了自身作为信号处理器,会拦截原本发给JVM的信号。解决方法是应该使用信号链式的本地代码更好地与JVM合作 6. Windows平台上,结构化异常处理(SEH)可用于把本地代码包裹在SEH try/catch块中捕捉机器(CPU/FPU)生成的软中断(如: 空指针访问冲突、除0操作等),在这些中断传播到JVM之前就得到处理,使JVM无法正常捕获到这些错误异常

0x4: JNI Code Example

在JNI框架柱,本地函数一般在单独的.c或.cpp文件中实现。当JVM调用这些函数,就传递

1. JNIEnv指针
2. jobject的指针 

env指向一个结构包含了到JVM的界面,包含了所有必须的函数与JVM交互、访问Java对象。基本上,Java程序可以做的任何事情都可以用JNIEnv做。下面代码把Java字符串转化为本地字符串

//C++ code
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv *env, jobject obj, jstring javaString)
{//Get the native string from javaStringconst char *nativeString = env->GetStringUTFChars(javaString, 0);//Do something with the nativeString//DON'T FORGET THIS LINE!!!env->ReleaseStringUTFChars(javaString, nativeString);
}/*C code*/
JNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv *env, jobject obj, jstring javaString)
{/*Get the native string from javaString*/const char *nativeString = (*env)->GetStringUTFChars(env, javaString, 0);/*Do something with the nativeString*//*DON'T FORGET THIS LINE!!!*/(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
}/*Objective-C code*/
JNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv *env, jobject obj, jstring javaString)
{/*DON'T FORGET THIS LINE!!!*/JNF_COCOA_ENTER(env);/*Get the native string from javaString*/NSString* nativeString = JNFJavaToNSString(env, javaString);/*Do something with the nativeString*//*DON'T FORGET THIS LINE!!!*/JNF_COCOA_EXIT(env);
}

本地数据类型与Java数据类型可以互相映射。对于复合数据类型,如对象,数组,字符串,就必须用JNIEnv中的方法来显示地转换
Relevant Link:

http://zh.wikipedia.org/wiki/Java%E6%9C%AC%E5%9C%B0%E6%8E%A5%E5%8F%A3
http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html
http://www.cnblogs.com/icejoywoo/archive/2012/02/22/2363709.html
http://www.ibm.com/developerworks/cn/java/j-jni/

 

3. Java Create New Process Native Function API Analysis In Linux

0x1: Java创建新进程涉及到的类、方法

1. java.lang.Runtime.exec(String[] cmdarray, String[] envp);

package com.tutorialspoint;public class RuntimeDemo {public static void main(String[] args) {try {// create a new array of 2 stringsString[] cmdArray = new String[2];// first argument is the program we want to opencmdArray[0] = "ls -l";// second argument is a parametercmdArray[1] = ".";// print a messageSystem.out.println("listing the current directory");Process process = Runtime.getRuntime().exec(cmdArray, null);// print another messageSystem.out.println("list directory is ok");} catch (Exception ex) {ex.printStackTrace();}}
}

Relevant Link:

http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec(java.lang.String[],%20java.lang.String[],%20java.io.File)
http://www.tutorialspoint.com/java/lang/runtime_exec_envp.htm

2. Process p = new ProcessBuilder("myCommand", "myArg").start();

package com.javacodegeeks.process;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;public class ProcessBuilderExample 
{public static void main(String[] args) throws InterruptedException, IOException {ProcessBuilder pb = new ProcessBuilder("echo", "This is ProcessBuilder Example from JCG");System.out.println("Run echo command");Process process = pb.start();int errCode = process.waitFor();System.out.println("Echo command executed, any errors? " + (errCode == 0 ? "No" : "Yes"));System.out.println("Echo Output:\n" + output(process.getInputStream()));    }private static String output(InputStream inputStream) throws IOException {StringBuilder sb = new StringBuilder();BufferedReader br = null;try {br = new BufferedReader(new InputStreamReader(inputStream));String line = null;while ((line = br.readLine()) != null) {sb.append(line + System.getProperty("line.separator"));}} finally {br.close();}return sb.toString();}
}

Relevant Link:

http://examples.javacodegeeks.com/core-java/lang/processbuilder/java-lang-processbuilder-example/
http://m.alvinalexander.com/java/java-exec-processbuilder-process-2
http://stackoverflow.com/questions/3468987/executing-another-application-from-java

0x2: difference between ProcessBuilder and Runtime.exec()

The various overloads of Runtime.getRuntime().exec(...) take either an array of strings or a single string. The single-string overloads of exec() will tokenise the string into an array of arguments, before passing the string array onto one of the exec() overloads that takes a string array. The ProcessBuilder constructors, on the other hand, only take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument. Either way, the arguments obtained are then joined up into a string that is passed to the OS to execute.

java下创建新进程的2种不同的方法的区别简单来说是这样的

1. exec
Runtime.getRuntime().exec("C:\DoStuff.exe -arg1 -arg2");2. ProcessBuilder
rocessBuilder b = new ProcessBuilder("C:\DoStuff.exe", "-arg1", "-arg2");List<String> params = java.util.Arrays.asList("C:\DoStuff.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
/*
1. ProcessBuilder.start() 和 Runtime.exec()传递的参数有所不同1) Runtime.exec()可接受一个单独的字符串,这个字符串是通过空格来分隔可执行命令程序和参数的,也可以接受字符串数组参数2) ProcessBuilder的构造函数是一个字符串列表或者数组。列表中第一个参数是可执行命令程序,其他的是命令行执行是需要的参数  2. 每个ProcessBuilder实例管理一个进程属性集。ProcessBuilder的start()方法利用这些属性创建一个新的Process实例。start()方法可以从同一实例重复调用,以利用相同或者相关的属性创建新的子进程3. ProcessBuilder还提供了一些额外的功能,例如1) 重复执行2) 设置环境变量 
*/

Relevant Link:

http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html
http://www.scala-lang.org/old/node/7146
http://stackoverflow.com/questions/6856028/difference-between-processbuilder-and-runtime-exec
http://lavasoft.blog.51cto.com/62575/15662/

0x3: Runtime.exec()源代码分析

/*
ProcessBuilder#start()} is now the preferred way to start a process with a modified environment.
*/
public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException 
{return new ProcessBuilder(cmdarray).environment(envp).directory(dir).start();
}

在JDK的实现中,Runtime.exec是只是一个包装函数,最终是通过调用ProcessBuilder实现的新进程创建

Relevant Link:

http://www.docjar.com/html/api/java/lang/Runtime.java.html

0x4: ProcessBuilder源代码分析

public Process start() throws IOException {// Must convert to array first -- a malicious user-supplied// list might try to circumvent the security check.String[] cmdarray = command.toArray(new String[command.size()]);cmdarray = cmdarray.clone();for (String arg : cmdarray)if (arg == null)throw new NullPointerException();// Throws IndexOutOfBoundsException if command is emptyString prog = cmdarray[0];SecurityManager security = System.getSecurityManager();if (security != null)security.checkExec(prog);String dir = directory == null ? null : directory.toString();try {return ProcessImpl.start(cmdarray,environment,dir,redirects,redirectErrorStream);} catch (IOException e) {// It's much easier for us to create a high-quality error// message than the low-level C code which found the problem.throw new IOException("Cannot run program \"" + prog + "\""+ (dir == null ? "" : " (in directory \"" + dir + "\")")+ ": " + e.getMessage(),e);}}

继续跟进ProcessImpl.start

// Only for use by ProcessBuilder.start()
static Process start(String[] cmdarray,java.util.Map<String,String> environment,String dir,ProcessBuilder.Redirect[] redirects,boolean redirectErrorStream)
throws IOException
{...return new UNIXProcess(toCString(cmdarray[0]),argBlock, args.length,envBlock, envc[0],toCString(dir),std_fds,redirectErrorStream);...
}

继续跟进UNIXProcess

//构造函数
UNIXProcess(final byte[] prog,final byte[] argBlock, final int argc,final byte[] envBlock, final int envc,final byte[] dir,final int[] fds,final boolean redirectErrorStream)throws IOException 
{ pid = forkAndExec(prog,argBlock, argc,envBlock, envc,dir,fds,redirectErrorStream);try {AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {public Void run() throws IOException {initStreams(fds);return null;}});} catch (PrivilegedActionException ex) {throw (IOException) ex.getException();}
}

继续跟进forkAndExec

/**
* Create a process using fork(2) and exec(2).
*
* @param fds an array of three file descriptors.
*        Indexes 0, 1, and 2 correspond to standard input,
*        standard output and standard error, respectively.  On
*        input, a value of -1 means to create a pipe to connect
*        child and parent processes.  On output, a value which
*        is not -1 is the parent pipe fd corresponding to the
*        pipe which has been created.  An element of this array
*        is -1 on input if and only if it is <em>not</em> -1 on
*        output.
* @return the pid of the subprocess
*/
private native int forkAndExec(byte[] prog,byte[] argBlock, int argc,byte[] envBlock, int envc,byte[] dir,int[] fds,boolean redirectErrorStream)
throws IOException;/**
* The thread factory used to create "process reaper" daemon threads.
*/
private static class ProcessReaperThreadFactory implements ThreadFactory 
{private final static ThreadGroup group = getRootThreadGroup();private static ThreadGroup getRootThreadGroup() {return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup> () {public ThreadGroup run() {ThreadGroup root = Thread.currentThread().getThreadGroup();while (root.getParent() != null)root = root.getParent();return root;}});}public Thread newThread(Runnable grimReaper) {// Our thread stack requirement is quite modest.Thread t = new Thread(group, grimReaper, "process reaper", 32768);t.setDaemon(true);// A small attempt (probably futile) to avoid priority inversion
        t.setPriority(Thread.MAX_PRIORITY);return t;}
}

forkAndExec是一个JNI函数,即它的实现代码是通过外部的.so文件实现的

//本机上是这个
./usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75.x86_64/jre/lib/amd64/libjava.so./usr/lib/jvm/java-1.8.0-openjdk-1.8.0.31-1.b13.el6_6.x86_64/jre/lib/amd64/libjava.so
./usr/lib/jvm/java-1.6.0-openjdk-1.6.0.34.x86_64/jre/lib/amd64/libjava.so

objdump -tT /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75.x86_64/jre/lib/amd64/libjava.so | grep forkAndExec

0000000000018330 g    DF .text    00000000000006fd  SUNWprivate_1.1 Java_java_lang_UNIXProcess_forkAndExec

\openjdk\jdk\src\solaris\native\java\lang\UNIXProcess_md.c

JNIEXPORT jint JNICALL Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,jobject process,jbyteArray prog,jbyteArray argBlock, jint argc,jbyteArray envBlock, jint envc,jbyteArray dir,jintArray std_fds,jboolean redirectErrorStream)
{...//创建新的子进程resultPid = startChild(c);assert(resultPid != 0);...
}

跟进resultPid = startChild(c);

static pid_t startChild(ChildStuff *c) 
{
#if START_CHILD_USE_CLONE
...return clone(childProcess, c->clone_stack + START_CHILD_CLONE_STACK_SIZE, CLONE_VFORK | CLONE_VM | SIGCHLD, c);
#elsevolatile pid_t resultPid = vfork();
#else//fork从当前进程中复制出子进程,fork是glibc库提供的包装函数,底层实现了fork()系统调用pid_t resultPid = fork();
#endifif (resultPid == 0)//新创建的子进程需要继续调用exec() API系列
        childProcess(c);assert(resultPid != 0);  /* childProcess never returns */return resultPid;
#endif /* ! START_CHILD_USE_CLONE */
}

继续跟进childProcess(c);

/*** Child process after a successful fork() or clone().* This function must not return, and must be prepared for either all* of its address space to be shared with its parent, or to be a copy.* It must not modify global variables such as "environ".*/
static int childProcess(void *arg)
{...JDK_execvpe(p->argv[0], p->argv, p->envv);...
}

继续跟进JDK_execvpe(p->argv[0], p->argv, p->envv);

/*** 'execvpe' should have been included in the Unix standards,* and is a GNU extension in glibc 2.10.** JDK_execvpe is identical to execvp, except that the child environment is* specified via the 3rd argument instead of being inherited from environ.*/
static void JDK_execvpe(const char *file, const char *argv[], const char *const envp[])
{if (envp == NULL || (char **) envp == environ) {//调用glibc的execvp,将新的进程文件载入内存,进行执行execvp(file, (char **) argv);return;}...
}

总结一下

1. Runtime.getRuntime().exec(cmd)的执行流程:
java.lang.Runtime.exec(cmd);
--java.lang.ProcessBuilder.start();
----java.lang.ProcessImpl.start();
------Java_java_lang_UNIXProcess_forkAndExec() in j2se/src/solaris/native/java/lang/UNIXProcess_md.c
--------1). fork(); 
--------2). execvp();2. Process p = new ProcessBuilder("myCommand", "myArg").start();的执行流程
--java.lang.ProcessBuilder.start();
----java.lang.ProcessImpl.start();
------Java_java_lang_UNIXProcess_forkAndExec() in j2se/src/solaris/native/java/lang/UNIXProcess_md.c
--------1). fork(); 
--------2). execvp();/*
需要注意的是,fork产生的子进程需要复制父进程在内存中的所有数据内容(代码段、数据段、堆栈段),由于全部复制开销较大,因此Linux已经采用copy-on-write机制,即只是复制页表,共享内容,在有改变的时候再去申请内存和复制数据
*/

Relevant Link:

https://searchcode.com/codesearch/view/17990470/
http://www.docjar.com/html/api/java/lang/ProcessBuilder.java.html
https://searchcode.com/codesearch/view/17994182/
https://searchcode.com/codesearch/view/17966870/
http://blog.csdn.net/bigdatahappy/article/details/40115077

 

4. Java Create New Process Native Function API Analysis In Windows

待研究

Relevant Link:

http://www.ibm.com/developerworks/cn/java/j-lo-processthread/
http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
http://www.ibm.com/developerworks/cn/java/j-lo-processthread/
http://openjdk.java.net/groups/hotspot/

 

Copyright (c) 2014 LittleHann All rights reserved

 

转载于:https://www.cnblogs.com/LittleHann/p/4326828.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小android模拟器,小姚Android模拟器工作室版本v6.2.7.0正式版

逍遥Android Emulator Studio Edition是高质量的Android模拟器. 此版本是特殊版本&#xff0c;支持无限的多打开&#xff0c;智能管理和组控制模式. 它是专门为需要商业营销的用户设计的. Xiaoyao Android Emulator Studio Edition具有强大的引擎和良好的兼容性全能营销王 安卓…

html5carousel图片轮播,jQuery响应式轮播图插件VM Carousel

插件描述&#xff1a;VM Carousel是一款jQuery响应式轮播图插件。该jquery轮播图插件支持自动播放模式&#xff0c;支持动态改变图片尺寸&#xff0c;支持居中模式&#xff0c;以及无限循环等。使用方法在页面中引入jquery.vm-carousel.css&#xff0c;jquery和jquery.vm-carou…

那是计算机房吗英语否定回答,【微课+教材+听力+知识点】PEP四年级英语下册 Unit 1...

原标题&#xff1a;【微课教材听力知识点】PEP四年级英语下册 Unit 1微课&#xff1a;Unit 1-PartA微课&#xff1a;Unit 1-PartB微课&#xff1a;Unit 1-PartC课文教材动画教材听力Unit 1 My schoolUnit 1 单词▲点右上方绿标即可收听Words in Unit 1first floor [ˌfɜːst ˈ…

PropertyGrid控件 分类(Category)及属性(Property)排序

最近在做表单设计器&#xff0c;设计器上的控件都是我们自己封装的&#xff0c;但每个属性类别里的属性是按照属性的拼音排序的&#xff0c;现在想按照PropertyIndex标识进行排序&#xff08;PropertyIndex的后三位是用来标识编辑器的&#xff09;。 具体实现如下&#xff1a; …

用计算机计算出密码,自带计算器的密码

手机、电脑都会有自带的计算器&#xff0c;用惯了简易的计算器功能&#xff0c;不知道有没有感觉 iPhone 自带的计算器难用&#xff1f;后来才发现原来它还可以使用科学计算器进行指数函数、对数函数和三角函数的计算。只需要将 iPhone 转到横排模式就可以&#xff1a;这算不算…

shopify在哪里填写html,[Shopify开店教程]添加嵌入代码

添加嵌入代码在Shopify管理员中创建购买按钮后&#xff0c;您就可以将其添加到您自己的网站或博客中。将嵌入代码添加到您网站的源HTML的过程有所不同&#xff0c;具体取决于您希望购买按钮和购物车在您的发布平台上显示的方式和位置&#xff0c;以及有时您在该平台上使用的主题…

activity生命周期图

转载于:https://www.cnblogs.com/aqianglala/p/4344431.html

华硕台式计算机光盘怎么启动不了,华硕笔记本怎么用光盘重装系统 笔记本重装系统失败怎么办...

华硕笔记本是现在非常热门的笔记本品牌&#xff0c;很多的华硕笔记本用户在重装系统的时候&#xff0c;大多数会用上光盘&#xff0c;这种重装方式较为简单&#xff0c;所以备受青眯&#xff0c;不过呢还是有很多电脑用户不知道怎么用光盘重装系统&#xff0c;没关系&#xff0…

怎么安装Win10,硬盘安装Win10系统图文教程

2019独角兽企业重金招聘Python工程师标准>>> http://jingyan.baidu.com/article/f25ef254613ffd482c1b8236.html 分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友…

游戏计算机重要参数,这真的很重要吗 游戏鼠标三大参数之谜

1游戏鼠标三大参数&#xff1a;采样率[中关村在线键鼠频道原创]游戏鼠标作为目前最受消费者关注的外设产品&#xff0c;其销量以及利润在市场上也是表现最为出色的&#xff0c;众多游戏外设厂商也推出各种各样的游戏鼠标&#xff0c;各种霸气的名字更是让我们看的眼花缭乱&…

桌面上的文件使计算机变慢吗,电脑用久了会变卡怎么办?让电脑变得流畅方法图解...

工作生活中我们的电脑时间用久了&#xff0c;就会变得很卡&#xff0c;那么如何做会让电脑变得流畅一点呢&#xff0c;小编教大家几招。步骤首先要保持windows桌面整洁&#xff0c;尽量少放一些文件&#xff0c;因为桌面上的文件都是放在C盘&#xff0c;电脑系统一般也是装在C盘…

美图秀秀计算机教程,美图秀秀怎么抠图 美图秀秀抠图详细教程

怎么抠图&#xff1f;这是很多人在进行图片处理过程中经常处理的问题。对于那些专业人士来说&#xff0c;他们大多数用的是PS软件。但是对于绝大多数没有接触过PS的小白来说&#xff0c;怎么抠图成为了一大难题。其实&#xff0c;用过美图秀秀这款软件的朋友来说&#xff0c;它…

磁盘及文件系统的管理

分区是为了创建文件系统MBR&#xff1a;创建分区后&#xff0c;为了能够快速的存取文件就有了文件系统inode&#xff1a;中存储了文件属组&#xff0c;等与文件数据没有关系的文件属性信息&#xff0c;但是没有文件名每次访问某个目录的文件时是会进行缓存的&#xff0c;在一定…

Cocos2d-x 3.8.1+Cocos Studio 2.3.2捉虫记之控制场景文件中的骨骼动画

Cocos2d-x 3.8.1Cocos Studio 2.3.2捉虫记之控制场景文件中的骨骼动画引子这段时间一直努力在把早期版本的拇指接龙游戏&#xff08;Cocos2d-x 2.2.3CocoStudio 1.4.0.1&#xff09;升级到当前相对稳定的高大上环境——Cocos2d-x 3.8.1Cocos Studio 2.3.2。行程中遇到不少麻烦&…

用JSmooth制作java jar文件的可运行exe文件教程【图文】

这是我之前在个人博客3yj上面写的一篇文章&#xff0c;如今转载过来&#xff0c;原文地址 &#xff08;这不是广告哦&#xff09; 几年前&#xff0c;刚接触java的是&#xff0c;就想用一些方法把自己的劳动果实保护起来&#xff0c;曾经也用过非常多这种工具&#xff0c;有一个…

全国计算机vb考试经典程序设计,全国计算机二级《VB语言程序设计》考试要点...

全国计算机二级《VB语言程序设计》考试要点VB语言程序设计是计算机二级考试的科目之一&#xff0c;考生们在备考是要熟悉科目的知识要点&#xff0c;有针对性地进行备考。下面百分网小编为大家搜索整理了关于二级《VB语言程序设计》考试要点&#xff0c;欢迎参考练习&#xff0…

MipMap

MipMap首先从MIPMAP的原理说起&#xff0c;它是把一张贴图按照2的倍数进行缩小。直到1X1。把缩小的图都存储起来。在渲染时&#xff0c;根据一个像素离眼睛为之的距离&#xff0c;来判断从一个合适的图层中取出texel颜色赋值给像素。在D3D和OGL都有相对应的API控制接 透过它的工…

windows2016服务器优化,Windows Server 2012 服务器优化图文方法

这篇文章主要介绍了Windows Server 2012 服务器优化图文方法,需要的朋友可以参考下1、显示桌面图片按下WinR键输入&#xff1a;rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,02、关闭IE增强的安全配置1.开启【服务器管理员】单击"服务器管理员"2.在左边窗格切…

ExtJs控件属性配置详细(转)

序言&#xff1a; 1.本文摘自网络&#xff0c;看控件命名像是4.0以前的版本&#xff0c;但控件属性配置仍然可以借鉴&#xff08;不足之处&#xff0c;以后项目用到时再续完善&#xff09;。 Ext.form.TimeField: 配置项&#xff1a; maxValue&#xff1a;列表中允许…

网站服务器中病毒该如何处理,网站被中了木马无法删除怎么办? 解决网站中病毒的办法...

紧急预警“XXCMS整站系统(XXCMS)”官方安装包被植入后门这是我们 前几天在站长网上公布的紧急预警! 但是还是有人中招了&#xff0c;服务器中了马&#xff0c;导致网站被挂了黑链&#xff0c;我们外星人源码安全小姐紧急响应&#xff0c;马上为其清除木马后门&#xff0c;查杀病…