60年代进程 80年代线程 IPC How the Java Virtual Machine (JVM) Works
小结:
1、
To facilitate communication between processes, most operating systems support Inter Process Communication (IPC) resources, such as pipes and sockets. IPC is used not just for communication between processes on the same system, but processes on different systems.
为促进进程间通信,许多操作系统支持内部进程间通信,例如管道和套接字。IPC不仅仅用于同一系统进程间通信,还用于不同的系统。
20年
https://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html
Processes and Threads
In concurrent programming, there are two basic units of execution: processes and threads. In the Java programming language, concurrent programming is mostly concerned with threads. However, processes are also important.
A computer system normally has many active processes and threads. This is true even in systems that only have a single execution core, and thus only have one thread actually executing at any given moment. Processing time for a single core is shared among processes and threads through an OS feature called time slicing.
It's becoming more and more common for computer systems to have multiple processors or processors with multiple execution cores. This greatly enhances a system's capacity for concurrent execution of processes and threads — but concurrency is possible even on simple systems, without multiple processors or execution cores.
Processes
A process has a self-contained execution environment. A process generally has a complete, private set of basic run-time resources; in particular, each process has its own memory space.
Processes are often seen as synonymous with programs or applications. However, what the user sees as a single application may in fact be a set of cooperating processes. To facilitate communication between processes, most operating systems support Inter Process Communication (IPC) resources, such as pipes and sockets. IPC is used not just for communication between processes on the same system, but processes on different systems.
Most implementations of the Java virtual machine run as a single process. A Java application can create additional processes using a ProcessBuilderobject. Multiprocess applications are beyond the scope of this lesson.
Threads
Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process.
Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication.
Multithreaded execution is an essential feature of the Java platform. Every application has at least one thread — or several, if you count "system" threads that do things like memory management and signal handling. But from the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section.
How the Java Virtual Machine (JVM) Works - CodeProject https://www.codeproject.com/articles/30422/how-the-java-virtual-machine-jvm-works
How the Java Virtual Machine (JVM) Works
Bikash Shaw, 25 Nov 2008
How the Java Virtual Machine Works: Inside the JVM.
Introduction
In high-level programming languages such as C and C++, we write a program in a human-readable format, and a program called a compiler translates it to a binary format called executable code that the computer can understand and execute. The executable code depends upon the computer machine that we use to execute our program; it is machine dependent. In Java, this process of writing to executing a program is very similar, but with one important difference that allows us to write Java programs that are machine independent.
Using an interpreter, all Java programs are compiled to an intermediate level called byte code. We can run the compiled byte code on any computer with the Java runtime environment installed on it. The runtime environment consists of a virtual machine and its supporting code.
JVM is an Emulation
The difficult part of creating Java byte code is that the source code is compiled for a machine that does not exist. This machine is called the Java Virtual Machine, and it exists only in the memory of our computer. Fooling the Java compiler into creating byte code for a nonexistent machine is only one-half of the ingenious process that makes the Java architecture neutral. The Java interpreter must also make our computer and the byte code file believe they are running on a real machine. It does this by acting as the intermediary between the Virtual Machine and our real machine. (See figure below.)
Java Virtual Machine Figure One
Figure 1 - JVM emulation run on a physical machine
The Java Virtual Machine is responsible for interpreting Java byte code and translating this into actions or Operating System calls. For example, a request to establish a socket connection to a remote machine will involve an Operating System call. Different Operating Systems handle sockets in different ways - but the programmer doesn't need to worry about such details. It is the responsibility of the JVM to handle these translations so that the Operating System and the CPU architecture on which the Java software is running is completely irrelevant to the developer. (See figure below.)
Java Virtual Machine Figure Two
Figure 2 - JVM handles translations
The Basic Parts of the Java Virtual Machine
Creating a Virtual Machine within our computer's memory requires building every major function of a real computer down to the very environment within which programs operate. These functions can be broken down into seven basic parts:
A set of registers
A stack
An execution environment
A garbage-collected heap
A constant pool
A method storage area
An instruction set
Registers
The registers of the Java Virtual Machine are similar to the registers in our computer. However, because the Virtual Machine is stack based, its registers are not used for passing or receiving arguments. In Java, registers hold the machine's state, and are updated after each line of byte code is executed, to maintain that state. The following four registers hold the state of the virtual machine:
frame, the reference frame, and contains a pointer to the execution environment of the current method.
optop, the operand top, and contains a pointer to the top of the operand stack, and is used to evaluate arithmetic expressions.
pc, the program counter, and contains the address of the next byte code to be executed.
vars, the variable register, and contains a pointer to local variables.
All these registers are 32 bits wide, and are allocated immediately. This is possible because the compiler knows the size of the local variables and the operand stack, and because the interpreter knows the size of the execution environment.
The Stack
The Java Virtual Machine uses an operand stack to supply parameters to methods and operations, and to receive results back from them. All byte code instructions take operands from the stack, operate on them, and return results to the stack. Like registers in the Virtual Machine, the operand stack is 32 bits wide.
The operand stack follows the last-in first-out (LIFO) methodology, and expects the operands on the stack to be in a specific order. For example, the isub byte code instruction expects two integers to be stored on the top of the stack, which means that the operands must have been pushed there by the previous set of instructions. isub pops the operands off the stack, subtracts them, and then pushes the results back onto the stack.
In Java, integers are a primitive data type. Each primitive data type has unique instructions that tell it how to operate on operands of that type. For example, the lsub byte code is used to perform long integer subtraction, the fsub byte code is used to perform floating-point subtraction, and the dsub byte code is used to perform long integer subtraction. Because of this, it is illegal to push two integers onto the stack and then treat them as a single long integer. However, it is legal to push a 64-bit long integer onto the stack and have it occupy two 32-bit slots.
Each method in our Java program has a stack frame associated with it. The stack frame holds the state of the method with three sets of data: the method's local variables, the method's execution environment, and the method's operand stack. Although the sizes of the local variable and the execution environment data sets are always fixed at the start of the method call, the size of the operand stack changes as the method's byte code instructions are executed. Because the Java stack is 32 bits wide, 64-bit numbers are not guaranteed to be 64-bit aligned.
The Execution Environment
The execution environment is maintained within the stack as a data set, and is used to handle dynamic linking, normal method returns, and exception generation. To handle dynamic linking, the execution environment contains symbolic references to methods and variables for the current method and current class. These symbolic calls are translated into actual method calls through dynamic linking to a symbol table.
Whenever a method completes normally, a value is returned to the calling method. The execution environment handles normal method returns by restoring the registers of the caller and incrementing the program counter of the caller to skip the method call instruction. Execution of the program then continues in the calling method's execution environment.
If execution of the current method completes normally, a value is returned to the calling method. This occurs when the calling method executes a return instruction appropriate to the return type.
If the calling method executes a return instruction that is not appropriate to the return type, the method throws an exception or an error. Errors that can occur include dynamic linkage failure, such as a failure to find a class file, or runtime errors, such as a reference outside the bounds of an array. When errors occur, the execution environment generates an exception.
The Garbage-Collected Heap
Each program running in the Java runtime environment has a garbage-collected heap assigned to it. Because instances of class objects are allocated from this heap, another word for the heap is memory allocation pool. By default, the heap size is set to 1MB on most systems.
Although the heap is set to a specific size when we start a program, it can grow, for example, when new objects are allocated. To ensure that the heap does not get too large, objects that are no longer in use are automatically deallocated or garbage-collected by the Java Virtual Machine.
Java performs automatic garbage collection as a background thread. Each thread running in the Java runtime environment has two stacks associated with it: the first stack is used for Java code; the second is used for C code. Memory used by these stacks is drawn from the total system memory pool. Whenever a new thread starts execution, it is assigned a maximum stack size for the Java code and for the C code. By default, on most systems, the maximum size of the Java code stack is 400KB, and the maximum size of the C code stack is 128KB.
If our system has memory limitations, we can force Java to perform more aggressive cleanup and thus reduce the total amount of memory used. To do this, reduce the maximum size of the Java and C code stacks. If our system has lots of memory, we can force Java to perform less aggressive cleanup, thus reducing the amount of background processing. To do this, increase the maximum size of the Java and C code stacks.
The Constant Pool
Each class in the heap has a constant pool associated with it. Because constants do not change, they are usually created at compile time. Items in the constant pool encode all the names used by any method in a particular class. The class contains a count of how many constants exist, and an offset that specifies where a particular listing of constants begins within the class description.
All information associated with a constant follows a specific format based on the type of the constant. For example, class-level constants are used to represent a class or an interface, and have the following format:
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
where tag is the value of CONSTANT_Class, and the name_index provides the string name of the class. The class name for int[][] is [[I. The class name for Thread[] is [Ljava.lang.Thread;.
The Method Area
Java's method area is similar to the compiled code areas of the runtime environments used by other programming languages. It stores byte code instructions that are associated with methods in the compiled code, and the symbol table the execution environment needs for dynamic linking. Any debugging or additional information that might need to be associated with a method is stored in this area as well.
The Byte Code Instruction Set
Although programmers prefer to write code in a high-level format, our computer cannot execute this code directly, which is why we must compile Java programs before we can run them. Generally, compiled code is either in a machine-readable format called machine language or in an intermediate-level format such as the assembly language or Java byte code.
The byte code instructions used by the Java Virtual Machine resemble Assembler instructions. If you have ever used Assembler, you know that the instruction set is streamlined to a minimum for the sake of efficiency, and that tasks, such as printing to the screen, are accomplished using a series of instructions. For example, the Java language allows us to print to the screen using a single line of code, such as:
System.out.println("Hello world!");
At compile time, the Java compiler converts the single-line print statement to the following byte code:
0 getstatic #6 <Field java.lang.System.out Ljava/io/PrintStream;>
3 ldc #1 <String "Hello world!">
5 invokevirtual #7 <Method java.io.PrintStream.println(Ljava/lang/String;)V>
8 return
The JDK provides a tool for examining byte code called the Java class file disassembler. We can run the disassembler by typing javap at the command line.
Because the byte code instructions are in such a low-level format, our programs execute at nearly the speed of programs compiled to machine language. All instructions in machine language are represented by byte streams of 0s and 1s. In a low-level language, byte streams of 0s and 1s are replaced by suitable mnemonics, such as the byte code instruction isub. As with assembly language, the basic format of a byte code instruction is:
<operation> <operands(s)>
Therefore, an instruction in the byte code instruction set consists of a 1-byte opcode specifying the operation to be performed, and zero or more operands that supply parameters or data that will be used by the operation.
Summary
The Java Virtual Machine exists only in the memory of our computer. Reproducing a machine within our computer's memory requires seven key objects: a set of registers, a stack, an execution environment, a garbage-collected heap, a constant pool, a method storage area, and a mechanism to tie it all together. This mechanism is the byte code instruction set.
To examine byte code, we can use the Java class file disassembler, javap. By examining bytecode instructions in detail, we gain valuable insight into the inner workings of the Java Virtual Machine and Java itself. Each byte code instruction performs a specific function of extremely limited scope, such as pushing an object onto the stack or popping an object off the stack. Combinations of these basic functions represent the complex high-level tasks defined as statements in the Java programming language. As amazing as it seems, sometimes dozens of byte code instructions are used to carry out the operation specified by a single Java statement. When we use these byte code instructions with the seven key objects of the Virtual Machine, Java gains its platform independence and becomes the most powerful and versatile programming language in the world.
JVM存在于内存中
60年代进程 80年代线程 IPC How the Java Virtual Machine (JVM) Works的更多相关文章
- Java Virtual Machine (JVM) objects 虚拟机实例的产生 退出 两种线程
Apache Spark is built around a distributed collection of immutable Java Virtual Machine (JVM) object ...
- 在 GitHub 复活 80 年代的游戏代码,它们出自第一本售出百万册的计算机书籍
今儿我在 GitHub 看到了一个很眼熟的名字和头像,但是第一时间没想起来他是谁.算了先看看是个什么神仙开源项目,竟然能登上今天的 GitHub 趋势榜首. 该项目是把<BASIC Comput ...
- Linux虚拟地址空间布局以及进程栈和线程栈总结【转】
转自:http://www.cnblogs.com/xzzzh/p/6596982.html 原文链接:http://blog.csdn.net/freeelinux/article/details/ ...
- Linux虚拟地址空间布局以及进程栈和线程栈总结
原文链接:http://blog.csdn.net/freeelinux/article/details/53782986[侵删] 本文转自多个博客,以及最后有我的总结.我没有单独从头到尾写一个总结的 ...
- 【摘】Linux虚拟地址空间布局以及进程栈和线程栈总结
在CSDN上看到的一篇文章,讲的还是满好的. 原文地址:Linux虚拟地址空间布局以及进程栈和线程栈总结 一:Linux虚拟地址空间布局 (转自:Linux虚拟地址空间布局) 在多任务操作系统中,每个 ...
- 进程间的通讯(IPC)方式
内存映射 为什么要进行进程间的通讯(IPC (Inter-process communication)) 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间共享数据 ...
- (day29) 进程互斥锁 + 线程
目录 进程互斥锁 队列和堆栈 进程间通信(IPC) 生产者和消费者模型 线程 什么是线程 为什么使用线程 怎么开启线程 线程对象的属性 线程互斥锁 进程互斥锁 进程间数据不共享,但是共享同一套文件系统 ...
- day37 GIL、同步、异步、进程池、线程池、回调函数
1.GIL 定义: GIL:全局解释器锁(Global Interpreter Lock) 全局解释器锁是一种互斥锁,其锁住的代码是全局解释器中的代码 为什么需要全局解释器锁 在我们进行代码编写时,实 ...
- day35:线程队列&进程池和线程池&回调函数&协程
目录 1.线程队列 2.进程池和线程池 3.回调函数 4.协程:线程的具体实现 5.利用协程爬取数据 线程队列 1.线程队列的基本方法 put 存 get 取 put_nowait 存,超出了队列长度 ...
随机推荐
- C++中派生类使用基类成员的问题
在C++中,派生类在定义构造函数时,会调用基类构造函数首先完成基类部分的构造: class Derive : public Base { public: Derive(string nam, int ...
- Numpy的基本操作和相关概念(一)
基础操作 np.random.randn() 符合正态分布的数据 np.vstack((a,b)) 矩阵水平拼接 np.hstack((a,b)) 矩阵垂直拼接 np.dot(a,c) 点阵积 A@B ...
- POJ 1383 Labyrinth (树的直径求两点间最大距离)
Description The northern part of the Pyramid contains a very large and complicated labyrinth. The la ...
- 算法导论 第一章and第二章(python)
算法导论 第一章 算法 输入--(算法)-->输出 解决的问题 识别DNA(排序,最长公共子序列,) # 确定一部分用法 互联网快速访问索引 电子商务(数值算 ...
- shelve -- 用来持久化任意的Python对象
这几天接触了Python中的shelve这个module,感觉比pickle用起来更简单一些,它也是一个用来持久化Python对象的简单工具.当我们写程序的时候如果不想用关系数据库那么重量级的东东去存 ...
- (转)php_curl模拟登录有验证码实例
三年来的第一篇博客,还记得那是一个夜深人静的夜晚, 独自一人坐在不到10平米的小屋里,指头迅速的敲打着键盘,这天真TMD热.BJ生活啊. 唉! 最近一直在参加一个论坛批量发帖的项目开发. 模拟登录,模 ...
- window查看哪些端口被占用命令
管理员方式运行cmd netstat -n
- 什么是Istio
本文主要是对Istio Prelim 1.0(https://preliminary.istio.io/docs/)的翻译 Istio:一种开放式平台,用于连接,管理和保护微服务. Istio提供了一 ...
- [luoguP1273] 有线电视网(DP)
传送门 f[i][j]表示节点i选j个用户的最大收益 #include <cstdio> #include <cstring> #include <iostream> ...
- POJ3621 Sightseeing Cows【最短路】
题目大意:在一个无向图里找一个环,是的点权和除以边权和最大 思路:UVA11090姊妹题 事实上当这题点权和都为1时就是上一题TUT #include <stdio.h> #include ...