扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
import java.awt.BorderLayout;
成都网站建设哪家好,找成都创新互联公司!专注于网页设计、成都网站建设、微信开发、微信小程序开发、集团成都企业网站定制等服务项目。核心团队均拥有互联网行业多年经验,服务众多知名企业客户;涵盖的客户类型包括:成都橡塑保温等众多领域,积累了大量丰富的经验,同时也获得了客户的一致称誉!
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
class CalculatorPanel extends JPanel {
private JPanel jp; // 中间的面板
private double result; // 计算结果
private boolean start; // 用于判断是否是首次输入,true首次,false不是首次
private boolean flag; // 用于判断是否清空显示区域的值,true需要,false不需要
private String lastCommand; // 用于保存运算符
JButton display; // 显示区域
public CalculatorPanel() {
// 初始化各项值
result = 0;
start = true;
flag = false;
lastCommand = "=";
// 设置CalculatorPanel这个面板的布局为框架布局
setLayout(new BorderLayout());
// 这个按钮用来显示值的区域
display = new JButton("0.0");
display.setEnabled(false);// 按钮样式设置为禁用样式
// 用来初始化,清除用的
JButton clear = new JButton("clear");
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 作初始化的操作
result = 0;
start = true;
flag = false;
lastCommand = "=";
display.setText("0.0");
}
});
jp = new JPanel();
// 将此面板布局设置为网格布局,4行4列
jp.setLayout(new GridLayout(4, 4));
// 实例化监听器对象
NumberAction na = new NumberAction();
CommandAction ca = new CommandAction();
makeButton("7", na);
makeButton("8", na);
makeButton("9", na);
makeButton("/", ca);
makeButton("4", na);
makeButton("5", na);
makeButton("6", na);
makeButton("*", ca);
makeButton("1", na);
makeButton("2", na);
makeButton("3", na);
makeButton("-", ca);
makeButton("0", na);
makeButton(".", na);
makeButton("+", ca);
makeButton("=", ca);
// 将面板,两个按键加入到我的面板,实现计算器的界面
add(display, BorderLayout.NORTH);
add(jp, BorderLayout.CENTER);
add(clear, BorderLayout.SOUTH);
}
private void makeButton(String buttonName, ActionListener al) {
JButton jb = new JButton(buttonName);
jp.add(jb);
jb.addActionListener(al);
}
// 数字监听器
private class NumberAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton jb = (JButton) e.getSource(); // 获取事件源对象
String input = jb.getText(); // 获取事件源对象上的标签
if (start) { // 首次输入
// 一上就".",就什么也不做
if (input.equals(".")) {
return;
}
// 如果是"0.0"的话,就清空
if (display.getText().equals("0.0")) {
display.setText("");
}
start = false;// 改变是否首次输入的标记值
} else {
// 判断显示区域的值里面是否已经有".",如果有,输入的又是".",就什么都不做
if (display.getText().indexOf(".") != -1) {
if (input.equals(".")) {
return;
}
}
// 判断显示区域的值里面只有"-",输入的又是".",就什么都不做
if (display.getText().equals("-")) {
if (input.equals(".")) {
return;
}
}
// 判断显示区域的值如果是"0",输入的不是".",就什么也不做
if (display.getText().equals("0")) {
if (!input.equals(".")) {
return;
}
}
}
// 如果我点击了运算符以后,再输入数字的话,就要清空显示区域的值
if (flag) {
display.setText("");
flag = false;// 还原初始值,不需要清空
}
display.setText(display.getText() + input);// 设置显示区域的值
}
}
// 运算符监听器
private class CommandAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton jb = (JButton) e.getSource(); // 获取事件源对象
String inputCommand = jb.getText(); // 获取事件源对象上的标签
if (start) {// 首次输入
// 一上就是"-"
if (inputCommand.equals("-")) {
display.setText("-");// 显示区域的内容设置为"-"
start = false;// 改变首次输入的标记
}
} else {
if (!flag) {// 如果flag=false不需要清空显示区的值,就调用方法计算
calculate(Double.parseDouble(display.getText()));// 保存显示区域的值,并计算
}
// 保存你点击的运算符
lastCommand = inputCommand;
flag = true;// 因为我这里已经输入过运算符,
}
}
}
// 计算用的方法
private void calculate(double x) {
if (lastCommand.equals("+")) {
result += x;
} else if (lastCommand.equals("-")) {
result -= x;
} else if (lastCommand.equals("*")) {
result *= x;
} else if (lastCommand.equals("/")) {
result /= x;
} else if (lastCommand.equals("=")) {
result = x;
}
display.setText("" + result);
}
}
class MyFrameUitl {
public static void init(JFrame jFrame, Dimension frameSize, String title,
String iconFileName, boolean resizable) {
Toolkit tk = Toolkit.getDefaultToolkit(); // 系统工具包,可以读取系统信息
Dimension screenSize = tk.getScreenSize();// 获取屏幕大小
// 获取宽高
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
// 找中心点
int centerX = screenWidth / 2;
int centerY = screenHeight / 2;
// 解析窗体大小
int frameWidth = frameSize.width;
int frameHeight = frameSize.height;
// 设置窗体位置
jFrame.setBounds(centerX - frameWidth / 2, centerY - frameHeight / 2,
frameWidth, frameHeight);
jFrame.setTitle(title);// 设置标题
if (iconFileName != null) {
jFrame.setIconImage(tk.getImage(iconFileName));// 设置图标
}
// 设置皮肤com.sun.java.swing.plaf.windows.WindowsLookAndFeel
/**/
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(jFrame);
} catch (Exception e1) {
e1.printStackTrace();
}
jFrame.setResizable(resizable);// 设置窗体是否可以改变大小
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置程序关闭动作
jFrame.setVisible(true);// 显示窗体
}
}
class CalculatorFrame extends JFrame {
public CalculatorFrame() {
add(new CalculatorPanel());
MyFrameUitl.init(this, new Dimension(400, 300), "简易计算器", null,
false);
this.pack();// 让组件按原始大小显示,并且窗体的大小刚好能够容纳所有的组件
}
}
public class CalculatorTest {
public static void main(String[] args) {
new CalculatorFrame();
}
}
运行结果:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@SuppressWarnings("serial")
public class OptimizeCalculator extends JFrame implements ActionListener{
JFrame frame;
//基本按钮
private JButton jia=new JButton("+");
private JButton jian=new JButton("-");
private JButton cheng=new JButton("*");
private JButton chu=new JButton("/");
private JButton qiuyi=new JButton("%");
private JButton deng=new JButton("=");
private JButton fu=new JButton("+/-");
private JButton dian=new JButton(".");
private JButton kai=new JButton("sqrt");
private JButton diao=new JButton("1/x");
private JButton aa=new JButton("A");
private JButton bb=new JButton("B");
private JButton cc=new JButton("C");
private JButton dd=new JButton("D");
private JButton ee=new JButton("E");
private JButton ff=new JButton("F");
JMenuItem copy,paste,s,t,help,about,me;//主菜单栏
JRadioButton sixteen,ten,eight,two;//单选按钮,进制切换
JButton backspace,ce,c,num0,num1,num2,num3,num4,num5,num6,num7,num8,num9;//数字按钮
private TextField k1=new TextField(); //可编辑的当行文本
private objConversion convert = new objConversion();//类的实例化
Container cp;//一个可包含其他 AWT 组件的组件
JTextField text;//编辑单行文本,和TextField具有兼容性,具有TextField不具有的功能
String copycontent="";
boolean clickable=true,clear=true;//clickable判断数字中是否已经有点 clear判断是否已经点了符号位,如:加减乘除
double qian; //点击符号是文本框已经存在的数字
String fuhao;//加减乘除。。。。符号
int jin=10,first=1;
//主体
public OptimizeCalculator(){
setTitle("计算器-李晓明制作");
setSize(400,300);//窗口的显示大小
setLocation(250,200);//在电脑屏幕的位置
text=new JTextField(25);//构造一个具有指定列数的新的空 TextField。
text.setText("0.");//将此 TextComponent 文本设置为指定文本。
text.setHorizontalAlignment(JTextField.RIGHT);//返回文本的对齐方式,从右到左
JPanel cp1=new JPanel();//JPanel 是一般轻量级容器
JPanel cp2=new JPanel();
JPanel cp3=new JPanel();
cp=getContentPane();//返回此窗体的 contentPane 对象
cp.add(cp1,"North");// 将指定的组件添加到此容器的指定位置。
cp.add(cp2,"Center");
cp.add(cp3,"South");
cp1.setLayout(new GridLayout(1,6));//设置此容器的布局管理器。
cp2.setLayout(new GridLayout(2,4));
cp3.setLayout(new GridLayout(6,6));
sixteen=new JRadioButton("十六进制");//创建一个具有指定文本的状态为未选择的单选按钮。
sixteen.setVisible(false);//使该组件可见或不可见。true 使该组件可见;false 使其不可见
ten=new JRadioButton("十进制",true);//创建一个具有指定文本和选择状态的单选按钮
ten.setVisible(false);
eight=new JRadioButton("八进制");
eight.setVisible(false);
two=new JRadioButton("二进制");
two.setVisible(false);
sixteen.addActionListener(this);//将一个 ActionListener(监听器) 添加到按钮中。
ten.addActionListener(this);
eight.addActionListener(this);
two.addActionListener(this);
//使用相同的 ButtonGroup 对象创建一组按钮意味着“开启”其中一个按钮时,将关闭组中的其他所有按钮。
ButtonGroup btg=new ButtonGroup();
btg.add(sixteen);
btg.add(ten);
btg.add(eight);
btg.add(two);
//计算器布局设置开始
cp1.add(text);
text.setEditable(false);//设置指定的 boolean 变量,以指示此 TextComponent 是否应该为可编辑的。
text.setBackground(new Color(255, 255, 255));//设置此组件的背景色。背景色仅在组件是不透明时才使用
cp2.add(sixteen);
cp2.add(ten);
cp2.add(eight);
cp2.add(two);
backspace=new JButton("Backspace");
backspace.setForeground(new Color(255,0,0));
backspace.addActionListener(this);
ce=new JButton("CE");
ce.setForeground(new Color(255,0,0));
ce.addActionListener(this);
c=new JButton("C");
c.setForeground(new Color(255,0,0));
c.addActionListener(this);
k1.setVisible(false);//设置不可见
cp2.add(k1);
cp2.add(backspace);
cp2.add(ce);
cp2.add(c);
num0=new JButton("0");
num1=new JButton("1");
num2=new JButton("2");
num3=new JButton("3");
num4=new JButton("4");
num5=new JButton("5");
num6=new JButton("6");
num7=new JButton("7");
num8=new JButton("8");
num9=new JButton("9");
cp3.add(num7);
num7.addActionListener(this);
cp3.add(num8);
num8.addActionListener(this);
cp3.add(num9);
num9.addActionListener(this);
cp3.add(chu);
chu.setForeground(new Color(255,0,0));
chu.addActionListener(this);
cp3.add(kai);
kai.addActionListener(this);
cp3.add(num4);
num4.addActionListener(this);
cp3.add(num5);
num5.addActionListener(this);
cp3.add(num6);
num6.addActionListener(this);
cp3.add(cheng);
cheng.setForeground(new Color(255,0,0));
cheng.addActionListener(this);
cp3.add(qiuyi);
qiuyi.addActionListener(this);
cp3.add(num1);
num1.addActionListener(this);
cp3.add(num2);
num2.addActionListener(this);
cp3.add(num3);
num3.addActionListener(this);
cp3.add(jian);
jian.setForeground(new Color(255,0,0));
jian.addActionListener(this);
cp3.add(diao);
diao.addActionListener(this);
cp3.add(num0);
num0.addActionListener(this);
cp3.add(fu);
fu.addActionListener(this);
cp3.add(dian);
dian.addActionListener(this);
cp3.add(jia);
jia.setForeground(new Color(255,0,0));
jia.addActionListener(this);
cp3.add(deng);
deng.setForeground(new Color(255,0,0));
deng.addActionListener(this);
cp3.add(aa);
aa.addActionListener(this);
cp3.add(bb);
bb.addActionListener(this);
cp3.add(cc);
cc.addActionListener(this);
cp3.add(dd);
dd.addActionListener(this);
cp3.add(ee);
ee.addActionListener(this);
cp3.add(ff);
ff.addActionListener(this);
aa.setVisible(false);
bb.setVisible(false);
cc.setVisible(false);
dd.setVisible(false);
ee.setVisible(false);
ff.setVisible(false);
//设置计算器布局结束
//菜单设置
JMenuBar mainMenu = new JMenuBar();
setJMenuBar(mainMenu);
JMenu editMenu = new JMenu("编辑");
JMenu viewMenu = new JMenu("查看");
JMenu helpMenu = new JMenu("帮助");
mainMenu.add(editMenu);
mainMenu.add(viewMenu);
mainMenu.add(helpMenu);
copy = new JMenuItem(" 复制");
paste = new JMenuItem(" 粘贴");
//表示键盘或等效输入设置上的键操作的 KeyStroke
KeyStroke copyks=KeyStroke.getKeyStroke(KeyEvent.VK_C,Event.CTRL_MASK);
copy.setAccelerator(copyks);//设置菜单选项加上快捷键
KeyStroke pasteks=KeyStroke.getKeyStroke(KeyEvent.VK_V,Event.CTRL_MASK);
paste.setAccelerator(pasteks);//设置菜单选项加上快捷键
editMenu.add(copy);
editMenu.add(paste);
copy.addActionListener(this);
paste.addActionListener(this);
t = new JMenuItem("●标准型");
s = new JMenuItem(" 科学型");
viewMenu.add(t);
viewMenu.add(s);
t.addActionListener(this);
s.addActionListener(this);
help = new JMenuItem(" 帮助主题");
about = new JMenuItem(" 关于计算器");
me = new JMenuItem(" 作者主页");
helpMenu.add(help);
helpMenu.add(about);
helpMenu.add(me);
help.addActionListener(this);
about.addActionListener(this);
me.addActionListener(this);
//菜单设置结束
//结束窗口
addWindowListener(new WindowDestroyer());
}
看过一个浪潮的接口调用。
金蝶的没做过。
你看下对你有没有帮助:
第一个版本,使用浪潮的凭证接口,按要求生成txt文件,然后在浪潮中导入txt文件。
第二个版本,跟踪浪潮凭证保存时候的SQL语句,分析出相关的数据库操作,直接写数据库。
不论凭证导入浪潮是使用哪种方法,前期的工作都是一样的,主要是各种基础数据的匹配,如:科目的匹配、核算项目的匹配等。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Calculator extends JFrame implements ActionListener
{
private boolean dotExist, operated, equaled; // 帮助运算的布尔变量
private double storedNumber; // 目前的结果
private char lastOperator; // 表示上一运算符
private JTextField operation; // 结果栏
private JButton dot, plus, minus, multi, div, sqrt, equal, changePN, clear; // 运算符
private JButton[] numbers; // 数字
// 构造者
public Calculator()
{
setTitle("Calculator");
// 初始化变量
dotExist = false; // 表示当前的数是否有小数点
operated = false; // 表示任意运算符是否被按下
equaled = false; // 表示等号是否被按下
storedNumber = 0;
lastOperator = '?';
// 初始化窗口变量
operation = new JTextField("0");
operation.setEditable(false);
numbers = new JButton[10];
for (int i = 0; i 10; i++)
numbers[i] = new JButton("" + i);
dot = new JButton(".");
plus = new JButton("+");
minus = new JButton("-");
multi = new JButton("*");
div = new JButton("/");
sqrt = new JButton("√");
equal = new JButton("=");
changePN = new JButton("±");
clear = new JButton("AC");
// 将窗口物体放入窗口
GridBagLayout layout = new GridBagLayout();
getContentPane().setLayout(layout);
addComponent(layout, operation, 0, 0, 4, 1);
addComponent(layout, numbers[1], 1, 0, 1, 1);
addComponent(layout, numbers[2], 1, 1, 1, 1);
addComponent(layout, numbers[3], 1, 2, 1, 1);
addComponent(layout, numbers[4], 2, 0, 1, 1);
addComponent(layout, numbers[5], 2, 1, 1, 1);
addComponent(layout, numbers[6], 2, 2, 1, 1);
addComponent(layout, numbers[7], 3, 0, 1, 1);
addComponent(layout, numbers[8], 3, 1, 1, 1);
addComponent(layout, numbers[9], 3, 2, 1, 1);
addComponent(layout, dot, 4, 0, 1, 1);
addComponent(layout, numbers[0], 4, 1, 1, 1);
addComponent(layout, sqrt, 4, 2, 1, 1);
addComponent(layout, plus, 1, 3, 1, 1);
addComponent(layout, minus, 2, 3, 1, 1);
addComponent(layout, multi, 3, 3, 1, 1);
addComponent(layout, div, 4, 3, 1, 1);
addComponent(layout, equal, 5, 0, 2, 1);
addComponent(layout, changePN, 5, 2, 1, 1);
addComponent(layout, clear, 5, 3, 1, 1);
}
// 对按钮进行反应的方法
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
if (btn == clear)
{
operation.setText("0");
dotExist = false;
storedNumber = 0;
lastOperator = '?';
}
else if (btn == equal)
{
operate('=');
equaled = true;
}
else if (btn == plus)
{
operate('+');
equaled = false;
}
else if (btn == minus)
{
operate('-');
equaled = false;
}
else if (btn == multi)
{
operate('*');
equaled = false;
}
else if (btn == div)
{
operate('/');
equaled = false;
}
else if (btn == changePN)
{
operate('p');
operate('=');
equaled = true;
}
else if (btn == sqrt)
{
operate('s');
operate('=');
equaled = true;
}
else
{
if (equaled)
storedNumber = 0;
for (int i = 0; i 10; i++)
if (btn == numbers[i])
{
if (operation.getText().equals("0"))
operation.setText("" + i);
else if(! operated)
operation.setText(operation.getText() + i);
else
{
operation.setText("" + i);
operated = false;
}
}
if (btn == dot ! dotExist)
{
operation.setText(operation.getText() + ".");
dotExist = true;
}
}
}
// 进行运算的方法
private void operate(char operator)
{
double currentNumber = Double.valueOf(operation.getText()).doubleValue();
if (lastOperator == '?')
storedNumber = currentNumber;
else if (lastOperator == '+')
storedNumber += currentNumber;
else if (lastOperator == '-')
storedNumber -= currentNumber;
else if (lastOperator == '*')
storedNumber *= currentNumber;
else if (lastOperator == '/')
storedNumber /= currentNumber;
else if (lastOperator == 'p')
storedNumber *= -1;
else if (lastOperator == 's')
storedNumber = Math.sqrt(currentNumber);
else if (lastOperator == '=' equaled)
storedNumber = currentNumber;
operation.setText("" + storedNumber);
operated = true;
lastOperator = operator;
}
// 快捷使用GridBagLayout的方法
private void addComponent(GridBagLayout layout, Component component, int row, int col, int width, int height)
{
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(10, 2, 10, 2);
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = col;
constraints.gridy = row;
constraints.gridwidth = width;
constraints.gridheight = height;
layout.setConstraints(component, constraints);
if (component instanceof JButton)
((JButton)component).addActionListener(this);
getContentPane().add(component);
}
// 主方法初始化并显示窗口
public static void main(String[] args)
{
Calculator calc = new Calculator();
calc.setSize(290, 400);
calc.setVisible(true);
}
}
Java技术与Java虚拟机中文JAVA技术网g0cVV+]
中文JAVA技术网I5Zz[ }'Og G6Y
说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API)。它们的关系如下图所示:
[)|)k3b9M#\)w%Q{~r0中文JAVA技术网:cP+] _2tRtm*K
中文JAVA技术网yz;_Y0FB
图1 Java四个方面的关系
,YWx ^L |Q0运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件)。最后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。从上图也可以看出Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,用Java语言编写并编译的程序可以运行在这个平台上。这个平台的结构如下图所示:
x[+DX0\:W-o@a0中文JAVA技术网"? c3Y6bj-_
中文JAVA技术网P @+O3lf_pJ b
中文JAVA技术网5h:OY TyL2\|Z
在Java平台的结构中, 可以看出,Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。它的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作系统上实现;在JVM 的上方是Java的基本类库和扩展类库以及它们的API, 利用Java API编写的应用程序(application) 和小程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java 的平台无关性。
h6l-v;HV1SvYO0中文JAVA技术网-G5cAK(e w}
那么到底什么是Java虚拟机(JVM)呢?通常我们谈论JVM时,我们的意思可能是:中文JAVA技术网,T,Y5d(B5r
中文JAVA技术网yWv~s;J
对JVM规范的的比较抽象的说明;
b0r[/o_k+p0对JVM的具体实现;中文JAVA技术网Xdt8M1sP T_"_s
在程序运行期间所生成的一个JVM实例。中文JAVA技术网H k0g,~ hO\
中文JAVA技术网C3@ w6O-a
对JVM规范的的抽象说明是一些概念的集合,它们已经在书《The Java Virtual Machine Specification》(《Java虚拟机规范》)中被详细地描述了;对JVM的具体实现要么是软件,要么是软件和硬件的组合,它已经被许多生产厂商所实现,并存在于多种平台之上;运行Java程序的任务由JVM的运行期实例单个承担。在本文中我们所讨论的Java虚拟机(JVM)主要针对第三种情况而言。它可以被看成一个想象中的机器,在实际的计算机上通过软件模拟来实现,有自己想象中的硬件,如处理器、堆栈、寄存器等,还有自己相应的指令系统。中文JAVA技术网nC/D IHP,|
A)R-DFw o2X0JVM在它的生存周期中有一个明确的任务,那就是运行Java程序,因此当Java程序启动的时候,就产生JVM的一个实例;当程序运行结束的时候,该实例也跟着消失了。下面我们从JVM的体系结构和它的运行过程这两个方面来对它进行比较深入的研究。
Z6?gXm!~0Java虚拟机的体系结构
2XFZ@"I I,\0
e-i'_;P X a0刚才已经提到,JVM可以由不同的厂商来实现。由于厂商的不同必然导致JVM在实现上的一些不同,然而JVM还是可以实现跨平台的特性,这就要归功于设计JVM时的体系结构了。中文JAVA技术网{ v2TtMlG?"]*N
中文JAVA技术网,HK3YQN k
我们知道,一个JVM实例的行为不光是它自己的事,还涉及到它的子系统、存储区域、数据类型和指令这些部分,它们描述了JVM的一个抽象的内部体系结构,其目的不光规定实现JVM时它内部的体系结构,更重要的是提供了一种方式,用于严格定义实现时的外部行为。每个JVM都有两种机制,一个是装载具有合适名称的类(类或是接口),叫做类装载子系统;另外的一个负责执行包含在已装载的类或接口中的指令,叫做运行引擎。每个JVM又包括方法区、堆、Java栈、程序计数器和本地方法栈这五个部分,这几个部分和类装载机制与运行引擎机制一起组成的体系结构图为:中文JAVA技术网BW0EZCI
2o\d oz0中文JAVA技术网%K1Hl:f ~(@Y(U
图3 JVM的体系结构中文JAVA技术网0P/b(jt U$x
7{F*d8f7ySt:Q0JVM的每个实例都有一个它自己的方法域和一个堆,运行于JVM内的所有的线程都共享这些区域;当虚拟机装载类文件的时候,它解析其中的二进制数据所包含的类信息,并把它们放到方法域中;当程序运行的时候,JVM把程序初始化的所有对象置于堆上;而每个线程创建的时候,都会拥有自己的程序计数器和Java栈,其中程序计数器中的值指向下一条即将被执行的指令,线程的Java栈则存储为该线程调用Java方法的状态;本地方法调用的状态被存储在本地方法栈,该方法栈依赖于具体的实现。中文JAVA技术网 t?!Pz!B]
"^x1MT5qj0下面分别对这几个部分进行说明。
/}C2v7b:]%vo[|0中文JAVA技术网'z/@1RG7[E1`8B
执行引擎处于JVM的核心位置,在Java虚拟机规范中,它的行为是由指令集所决定的。尽管对于每条指令,规范很详细地说明了当JVM执行字节码遇到指令时,它的实现应该做什么,但对于怎么做却言之甚少。Java虚拟机支持大约248个字节码。每个字节码执行一种基本的CPU运算,例如,把一个整数加到寄存器,子程序转移等。Java指令集相当于Java程序的汇编语言。中文JAVA技术网 ^sH2X*b,Z
q3[ OT`z"M4V0Java指令集中的指令包含一个单字节的操作符,用于指定要执行的操作,还有0个或多个操作数,提供操作所需的参数或数据。许多指令没有操作数,仅由一个单字节的操作符构成。
P.R.Uxbfc0
o"o qq9_0虚拟机的内层循环的执行过程如下:中文JAVA技术网3Hn8B r,xE
MjHj(zBG t"m P0do{
l$Iz V!M9[0取一个操作符字节;中文JAVA技术网7[?3o?,v A|3b+O R
根据操作符的值执行一个动作;
I(^e)G)Hf6`0}while(程序未结束)中文JAVA技术网y}0J/|:so
中文JAVA技术网c|%L(ud
由于指令系统的简单性,使得虚拟机执行的过程十分简单,从而有利于提高执行的效率。指令中操作数的数量和大小是由操作符决定的。如果操作数比一个字节大,那么它存储的顺序是高位字节优先。例如,一个16位的参数存放时占用两个字节,其值为:
0H.w`wb}.X0中文JAVA技术网y{X;n.u4PT+e)D7\E
第一个字节*256+第二个字节字节码。中文JAVA技术网"V[]J!_0v+D
5^t6E[3aW![0指令流一般只是字节对齐的。指令tableswitch和lookup是例外,在这两条指令内部要求强制的4字节边界对齐。
#Rop'v6w FS0中文JAVA技术网g8Ai _)iw8r
对于本地方法接口,实现JVM并不要求一定要有它的支持,甚至可以完全没有。Sun公司实现Java本地接口(JNI)是出于可移植性的考虑,当然我们也可以设计出其它的本地接口来代替Sun公司的JNI。但是这些设计与实现是比较复杂的事情,需要确保垃圾回收器不会将那些正在被本地方法调用的对象释放掉。
~:Jin+U$zE SI7Y0
"j1lJ`7Dd0v"v0Java的堆是一个运行时数据区,类的实例(对象)从中分配空间,它的管理是由垃圾回收来负责的:不给程序员显式释放对象的能力。Java不规定具体使用的垃圾回收算法,可以根据系统的需求使用各种各样的算法。中文JAVA技术网'z/wgb.s
中文JAVA技术网\TMY[:H)Z#@ tr
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流