java代码运行出来该设备有问题代码43,跪求解释

09:12 提问
我用Java 写的一个简单截图小工具 但是出现一些在重截时出现bug
/**在这里贴上我注释满满的代码 求一语道破 求建议 求批评
没有贴main 方法 随便写个main方法便可运行 */
package com.
import java.awt.AWTE
import java.awt.AlphaC
import java.awt.C
import java.awt.C
import java.awt.G
import java.awt.Graphics2D;
import java.awt.P
import java.awt.R
import java.awt.R
import java.awt.T
import java.awt.event.MouseE
import java.awt.event.MouseL
import java.awt.event.MouseMotionL
import java.awt.image.BufferedI
import java.io.F
import java.io.IOE
import javax.imageio.ImageIO;
import javax.swing.JF
import com.sun.awt.AWTU
public class ScreenCapture extends JFrame implements MouseListener,
MouseMotionListener {
private BufferedImage bufferedImage =// 用来存放图像
// 获取屏幕的大小
private int width = Toolkit.getDefaultToolkit().getScreenSize().
private int height = Toolkit.getDefaultToolkit().getScreenSize().
private Point point = new Point(0, height); // 截图的左上角
private Point point2 = new Point(0, 0);// 截图右下角
private Point point3 = new Point(0, 0);// 用来处理point 与point2 的关系
// 是画笔的透明度可控制
private AlphaC
boolean isStarCut = false, isEndCut =// isStarCut 为开始选区
// isEndCut为截图结束仅标记结束选区
public ScreenCapture() {
// 初始化窗口
this.InitScr();
private void InitScr() // 初始化
// 截取整个桌面作为窗口的背景
bufferedImage = new Robot().createScreenCapture(new Rectangle(0, 0,
width, height));
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 去掉窗体结构
this.setUndecorated(true);
// 设置窗体大小
this.setSize(width, height);
// 设置画笔的透明度
composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.setVisible(true);
this.setAlwaysOnTop(true);
repaint();
public void paint(Graphics g) {
// 配置截图环境
BufferedImage buff = new BufferedImage(width, height,
BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = buff.createGraphics(); // 画笔一
Graphics2D g3 = buff.createGraphics(); // 画笔二 用两个画笔主要是因为需要不同的透明度
g2.drawImage(bufferedImage, 0, 0, null);
g2.setColor(Color.gray);
g2.setComposite(composite);
g2.fillRect(0, 0, width, height);
// 截图的工作
if (isStarCut == true || isEndCut == true) { // 当
confirmArea(); // 处理坐标的方法
* 我实现的原理是 在铺了全屏截图的窗口上铺上一层灰色 透明为0.6 的实心矩形
* 根据用户在窗口拖动的坐标再另外截取一张相对应的图片铺在上面
g3.drawImage(bufferedImage.getSubimage(point.x, point.y, Math
.abs(point2.x - point.x), Math.abs(point2.y - point.y)),
point.x, point.y, null);
// 画出一个绿色的空心矩形
g3.setColor(Color.green);
g3.drawRect(point.x, point.y, point2.x - point.x, point2.y
- point.y);
// 功能框的显示
if (isEndCut == true) { // 当选区结束 才会绘出此框
g2.fillRect(point3.x, point3.y + 5, 200, 30);
g2.setColor(Color.red);
g3.drawRect(point3.x, point3.y + 5, 60, 30);
g3.setColor(Color.white);
g3.drawString("完成", point3.x + 20, point3.y + 25);
g2.drawRect(point3.x + 70, point3.y + 5, 60, 30);
g2.drawString("重截", point3.x + 20 + 70, point3.y + 25);
g2.drawRect(point3.x + 140, point3.y + 5, 60, 30);
g2.drawString("退出", point3.x + 20 + 140, point3.y + 25);
g.drawImage(buff, 0, 0, this);
// 调节功能框位置的方法
public void action()
if (point2.x &= width - 200 && point2.y & height - 35) {
point3.x = point2.x;
point3.y = point2.y;
} else if (point.x &= 200 && point.y &= 35) {
point3.x = point.x;
point3.y = point.y - 50;
else if (point.x &= 200 && point2.x &= width - 200 && point.y &= 35) {
point3.x = point2.x - 205;
point3.y = point.y - 50;
} else if (point.y &= 35 && point2.y &= height - 35
&& point2.x &= width - 200) {
point3.x = point2.x;
point3.y = point2.y;
point3.x = point2.x - 205;
point3.y = point.y;
public void confirmArea() {
point.x = point3.x; // 每一次开始都是和原点坐标比较
point.y = point3.y;
if (point2.x & point.x && point2.y & point.y) {
temp = point.x;
point.x = point2.x;
point2.x =
temp = point.y;
point.y = point2.y;
point2.y =
} else if (point2.x & point.x) {
temp = point.x;
point.x = point2.x;
point2.x =
} else if (point2.y & point.y) {
temp = point.y;
point.y = point2.y;
point2.y =
public void actoinCut(MouseEvent e) // 操作功能框的方法
if (isEndCut) {
if (e.getX() &= point3.x && e.getX() &= point3.x + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
// //将截好的图保存起来 原理是利用点下完成的“按钮”时的坐标 即是最后一次决定的选区 对图片进行截图保存
ImageIO.write(bufferedImage.getSubimage(point.x, point.y,
Math.abs(point2.x - point.x), Math.abs(point2.y
- point.y)), "jpg", new File("D:/D.jpg"));
} catch (IOException e1) {
// // TODO Auto-generated catch block
e1.printStackTrace();
System.exit(0); // 保存完毕马上退出 这里的保存够工作有点简单因为只是用来测试此截图工具的bug
// 具体的功能先不实现先
else if (e.getX() &= point3.x + 70
&& e.getX() &= point3.x + 70 + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
isEndCut = // 重新截图 一切进入初始状态 这个 重截一直搞不好 求大神
isStarCut =
// 点击重截后鼠标依然保持手型样式 所以要恢复默认
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
repaint();
else if (e.getX() &= point3.x + 140
&& e.getX() &= point3.x + 140 + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
System.exit(0);
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
if (e.getButton() == MouseEvent.BUTTON3) // 双击 右键退出程序
if (e.getClickCount() == 2)
System.exit(0);
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
// 只有当初始化状态才生效
if (isStarCut == false && isEndCut == false
&& e.getButton() == MouseEvent.BUTTON1) {
point.x = e.getX();
point.y = e.getY();
point3.x = e.getX();
point3.y = e.getY();
isStarCut =
// 进入重截的条件
else if (isEndCut) {
this.actoinCut(e);
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
// 截图开始生效
if (isStarCut && isEndCut == false
&& e.getButton() == MouseEvent.BUTTON1) {
isEndCut = // 鼠标一放开马上标记截图结束
isStarCut = // 重新标记未开始选区状态
repaint();// 重绘
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
// 拖动是改变矩形的坐标点
if (isStarCut || isEndCut) {
point2.x = e.getX();
point2.y = e.getY();
repaint();
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
// 在功能框上显示手型状态
if (isEndCut) {
if (e.getX() &= point3.x && e.getX() &= point3.x + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
setCursor(new Cursor(Cursor.HAND_CURSOR));
else if (e.getX() &= point3.x + 70
&& e.getX() &= point3.x + 70 + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
setCursor(new Cursor(Cursor.HAND_CURSOR));
else if (e.getX() &= point3.x + 140
&& e.getX() &= point3.x + 140 + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
setCursor(new Cursor(Cursor.HAND_CURSOR));
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
按赞数排序
int needWh = Math.abs(point2.x - point.x);
int needhg = Math.abs(point2.y - point.y);
if ((isStarCut || isEndCut) && needWh != 0 && needhg != 0) {
confirmArea(); // 处理坐标的方法
//将选择的矩形图片截出来
BufferedImage needScr = bufferedImage.getSubimage(point.x, point.y, needWh, needhg);
//截出来以后重新画在jframe上,覆盖原先背景图片,以不同的透明度
g3.drawImage(needScr,point.x, point.y, null);
g3.setColor(Color.RED);
g3.drawRect(point.x, point.y, point2.x - point.x, point2.y - point.y);
确定所选区域为正方形才继续截图,这样就不会报错。
其实最根本的原因在这个地方,就是当你点击完成、重截、退出的时候同样会触发mouseReleased事件,只要加一个标志就可以了:
boolean isRecapt =
//标记是否是重新截图
boolean isComplt =
//标记是否完成截图
boolean isExit =
//标记是否是退出
public void actoinCut(MouseEvent e) // 操作功能框的方法
if (isEndCut) {
if (e.getX() &= point3.x && e.getX() &= point3.x + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
isComplt =
//将截好的图保存起来 原理是利用点下完成的“按钮”时的坐标 即是最后一次决定的选区 对图片进行截图保存
ImageIO.write(bufferedImage.getSubimage(point.x, point.y,
Math.abs(point2.x - point.x), Math.abs(point2.y
- point.y)), "jpg", new File("JAVA截图_" + System.currentTimeMillis() + ".jpg"));
} catch (IOException e1) {
e1.printStackTrace();
System.exit(0);
else if (e.getX() &= point3.x + 70
&& e.getX() &= point3.x + 70 + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
isEndCut = // 重新截图 一切进入初始状态 这个 重截一直搞不好 求大神
isStarCut =
isRecapt = //重新截图置为true
// 点击重截后鼠标依然保持手型样式 所以要恢复默认
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
repaint();
else if (e.getX() &= point3.x + 140
&& e.getX() &= point3.x + 140 + 60
&& e.getY() &= point3.y + 5 && e.getY() &= point3.y + 35) {
System.exit(0);
public void mouseReleased(MouseEvent e) {
//当点击完成、重截、退出以后,现有程序会将释放鼠标(Release)的动作视为截图动作的开始,这显然是错误的,因此要过滤掉。
if (isRecapt || isComplt || isExit){
System.out.println("我return了 mouseReleased");
isRecapt =
repaint();// 重绘
// 截图开始生效
if (isStarCut && isEndCut == false
&& e.getButton() == MouseEvent.BUTTON1) {
isEndCut = // 鼠标一放开马上标记截图结束
isStarCut = // 重新标记未开始选区状态
repaint();// 重绘
594关注|579收录
1744关注|145收录
519关注|1023收录
其他相似问题
相关参考资料程序员面试必考题(21)-Java虚拟机、垃圾收集及代码安全_笔试面经_牛客网
程序员面试必考题(21)-Java虚拟机、垃圾收集及代码安全
微信公众号:开点工作室(ID:kaidiancs)
Java语言在最初开发时有明确的目标,这些也正是它区别于其他语言的独特之处,这些目标包括:
(1)创建一种面向对象的语言。面向对象的程序设计方法已成为主流,Java语言的语法及程序结构正是采用了这样的设计方法。
(2)提供一种解释环境,这可以缩短系统开发的编译-连接-装载-测试周期,提高开发速度。
(3)去掉了影响代码健壮性的功能,如指针结构及程序员负责的内存释放。
(4)为程序运行多线程提供了方法。
(5)允许程序下载代码模块,这样在程序运行生命期内可以动态修改它们。
(6)检查下载的代码模块,提供了保证安全的一种手段。
而Java虚拟机、垃圾收集机制及三级代码安全检查机制,使得Java得以实现这个目标。
Java虚拟机
Java virtual machine
程序必不可少的机制。编译后的
程序指令并不直接在硬件系统的
上执行,而是由
是编译后的
程序和硬件系统之间的接口,程序员可以把
看作一个虚拟的处理器。它不仅解释执行编译后的
指令,而且还进行安全检查。它是
程序能在多平台间进行无缝移植的可靠保证,同时也是
程序的安全检验引擎。
Java虚拟机规范中给出了JVM的定义:JVM是在一台真正的机器上用软件方式实现的一台假想机。JVM使用的代码存储在.class文件中。JVM的某些指令很像真正的CPU指令,包括算术运算、流控制和数组元素访问等。
Java虚拟机规范提供了编译所有Java代码的硬件平台。因为编译是针对假想机的,所以该规范能让Java程序独立于平台。它适用于每个具体的硬件平台,以保证能运行为JVM编译的代码。JVM不但可以用软件实现,而且可以用硬件实现。
JVM的具体实现包括:指令集(等价于CPU的指令集)、寄存器组、类文件格式、栈、垃圾收集堆、内存区。
JVM的代码格式为压缩的字节码,因而效率较高。由JVM字节码表示的程序必须保持原来的类型规定。Java主要的类型检查是在编译时由字节码校验器完成的。Java的任何解释器必须能执行符合JVM定义的类文件格式的任何类文件。
Java虚拟机规范对运行时数据区域的划分及字节码的优化并不做严格的限制,它们的实现依平台的不同而有所不同。JVM的实现叫做Java运行时系统或运行时环境(Runtime
Environment),简称为运行时。Java运行时必须遵从Java虚拟机规范,这样,Java编译器生成的类文件才可被所有Java运行时系统下载。嵌入了Java运行时系统的应用程序,就可以执行Java程序了。目前有许多操作系统和浏览器都嵌入了Java运行时环境。
在问世之初,因其没有完全优化,并且是解释执行,所以
程序的运行效率较低。同时,有着较长发展史、已非常成熟的
语言仍在开发界扮演着主要角色,人们往往拿
的性能效率与刚诞生的
相比较,这当然失之偏颇。
Java解释器经过不断的优化,字节码的执行速度已有很大提高。另外,在字节码执行之前可以先经过JIT编译器进行编译,生成针对具体平台的本机执行代码。它的执行效率可比解释执行的效率大幅度提高。现在许多厂商都提供JIT编译器,这项技术已非常成熟。由于字节码与平台无关,所以经过编译的Java仍不失跨平台的特点。
Hotspot技术是Sun公司推出的另一个有特色的技术。它提供对代码的运行时选择,为的是从根本上解决Java程序的效率问题。在程序执行时,Hotspot对每个字节码指令进行分析,根据它的执行次数,动态决定它的执行方式。比如,一段指令需要多次重复执行,则立即编译为可执行代码。如果是只执行一次的简单指令,且解释执行的效率更高,则使用解释执行的方式。有了这项技术,Java的效率问题基本上可以得到解决。
2.垃圾收集机制
许多程序设计语言允许在运行时动态分配内存。分配内存的过程因各种语言的语法不同而有所不同,但总要返回指向内存块开始地址的指针。
一旦不再需要所分配的内存(指向内存的指针超出使用范围),程序或运行时环境最好将内存释放,避免内存越界时得到意外结果。
在C和C++(及其他语言)中,由程序开发人员负责内存的释放。这是个很恼人的事情,因为程序开发人员并不总是知道内存应该在何时释放。如果不释放内存,那么当系统中没有内存可用时程序会崩溃。这些程序被称为有“内存漏洞”。
在Java中,程序员不必亲自释放内存,它提供了后台系统级线程,记录每次内存分配的情况,并统计每个内存指针的引用次数。在Java虚拟机运行时环境闲置时,垃圾收集线程将检查是否存在引用次数为0的内存指针,引用次数为0即意味着没有程序再使用这块内存;如果有这样的内存的话,则垃圾收集线程把该内存“标记”为“清除”(释放),就是要归还给系统,留待下次再分配给其他的内存申请。
在Java程序生存期内,垃圾收集将自动进行,无需用户释放内存,从而消除了内存漏洞。编制程序时,程序员可以将注意力放在更需注意的地方,不仅如此,程序的调试也更加方便。
3.代码安全
语言是解释执行的,但从某种意义来讲,
文件是“编译”的,因为它也生成了中间语言形式的文件。经过“编译”的
目标代码,称为字节码,存储在
文件中。字节码是不依赖于机器硬件平台的二进制代码。
运行时,类下载器下载组成Java程序的字节码,在解释器中检查并运行它们。在某些Java运行时环境中,验证过的字节码也可以被编译为本地的机器码,并直接在硬件平台上执行。
对于Applet,因其是从其他机器上通过网络下载到本机执行的,程序中可能隐藏某些非法操作,所以在Applet运行之前,系统要对之进行严格的三级代码安全检查,即验证、分析和跟踪监测。第一级验证是在类下载时完成的,检查从哪里下载文件,是否有权限进到本机系统。然后进行第二级检查,即字节码校验,此时要分析下载的字节码是否合乎规则。如果字节码的格式不合要求,则拒绝执行。完全合乎规则的字节码才允许执行。执行的时候,安全管理器始终监测所执行的每步操作,检查其合法性。Java的安全检查可以全面提高操作系统的安全等级,经过这三级安全检查的Java程序不会受到病毒的侵害。目前很多系统在做安全检查时只做第一步,即看代码下载的权限是否合乎要求。与之相比,Java的三级安全检查机制要完备得多,它不仅进行静态检查,还要进行动态跟踪。
具体地说,在Java的不同版本中,都有不同的安全机制。在最初的JDK1.0版本中,安全模型是所谓的“沙箱”模型,从网络上下载的代码只能在一个受限的环境中运行,这个环境象个箱子一样限制了代码能访问的资源。
在后来的JDK1.1版本中,提出了“签名Applet”的的概念。有正确签名的Applet视同本地代码一样,可以使用本地的资源。没有签名的Applet还与前一版本一样,只在沙箱中运行。
2平台下,安全机制又有较大改善。它允许用户自己设定相关的安全级别。另外,对于应用程序,也采取了和Applet一样的安全策略,程序员可以根据需要对本地代码或是远程代码进行设定,以保证程序更安全高效地运行。
在Java程序环境中,重要的几个组成部分包括Java解释器、类下载器及字节码校验器。
3.1 Java解释器
Java解释器只能执行为JVM编译的代码。Java解释器有三项主要工作:
(1)下载代码--由类下载器完成。
(2)校验代码--由字节码校验器完成。
(3)运行代码--由运行时解释器完成。
3.2 类下载器
Java运行时系统区别对待来自不同源的类文件。它可能从本地文件系统中下载类文件,也可能从Internet网上使用类下载器下载类文件。运行时系统动态决定程序运行时所需的类文件,并把它们下载到内存中,将类、接口与运行时系统相连接。类下载器把本地文件系统的类名空间和网络源输入的类名空间区分开来,以增加安全性。因为内置的类总是先被检查,所以可以防止起破坏作用的应用程序的侵袭。
所有的类下载完毕后,开始确定可执行文件的内存分配。此时,指定具体的内存地址,并创建查询表。因为内存分配是在运行时进行的,并且Java解释器阻止访问可能给操作系统带来破坏的非法代码地址,从而增加了保护性。
3.3 字节码校验器
Java代码在机器上真正执行前要经过几次测试。程序通过字节码校验器检查代码的安全性,字节码校验器检测代码段的格式,并使用规则来检查非法代码段--伪造的指针、对目标的访问权限违例或是试图改变目标类型或类的代码。通过网络传送的所有类文件都要经过字节码校验器的检验。
字节码校验器要对程序中的代码进行四趟扫描。这可以保证代码将依从JVM规范,并且不破坏系统的完整性。校验器主要检查以下几项内容:
(1)类遵从JVM的类文件格式。
(2)不出现访问违例情况。
(3)代码不会引起运算栈溢出。
(4)所有运算代码的参数类型总是正确的。
(5)不会发生非法数据转换,如把整数转换为指针。
(6)对象域访问是合法的。
如果完成所有的扫描之后不返回任何错误信息,就可以保证Java
程序的安全性了。
扫描二维码,关注牛客网
下载牛客APP,随时随地刷题
浙ICP备号-2
扫一扫,把题目装进口袋安卓android源码开发错误_bug解决方案_java异常_优良自学吧 |Javaweb文件下载,亲看图,急死我了!这个代码的访问路径是错了,求正确答案!!!跪求啊!!!!我也不知道正确的该怎么写,求大侠!!! - 开源中国社区
当前访客身份:游客 [
当前位置:
共有4个答案
<span class="a_vote_num" id="a_vote_num_
我在网上搜过,也有的不是这样写的,求正确写法!!
<span class="a_vote_num" id="a_vote_num_
把zip文件夹放到WebRoot下 把路径改成&ZIP/Z.zip
--- 共有 1 条评论 ---
解决了,谢谢!
(3年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
怎么能有 /web-inf这样的路径呢,J2EE的第一课都没学。
/web-inf 下的文件是不能被网络访问到的,只能被JAVA/JSP使用或读取,你要让文件被外部访问到,直接放到根目录即可
--- 共有 1 条评论 ---
是没学,只学了一些javaweb
(3年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
WEB-INF/出于保护机制,是不允许直接链接访问的。
你可以在其他地方建立目录访问。或者在代码里写个下载访问
--- 共有 1 条评论 ---
恩,弄好了
(3年前)&nbsp&
更多开发者职位上
有什么技术问题吗?
我不是方的其它问题
类似的话题

我要回帖

更多关于 手柄设备有问题代码43 的文章

 

随机推荐