Rust代码如何检查Java代码调用引发的异常?
我有调用Java方法的Rust代码:Rust代码如何检查Java代码调用引发的异常?,rust,java-native-interface,Rust,Java Native Interface,我有调用Java方法的Rust代码: let cls = je.find_class("com/purplefrog/batikExperiment/ToPixels")?; let width = 400; let height = 400; let rgbs = je.new_byte_array(width*height*3)?; let rgbs2:JObject = JObject::from(rgbs); let result = je.call_static_method(cl
let cls = je.find_class("com/purplefrog/batikExperiment/ToPixels")?;
let width = 400;
let height = 400;
let rgbs = je.new_byte_array(width*height*3)?;
let rgbs2:JObject = JObject::from(rgbs);
let result = je.call_static_method(cls, "renderTo", "(II[B)V", &[
JValue::from(width),
JValue::from(height),
JValue::from(rgbs2),
])?;
当我运行它时,会收到很多警告,如:
本机方法中的警告:当需要从CallVoidMethod调用时,JNI调用未检查异常
位于sun.dc.pr.PathStroker.dispose(本机方法)
在sun.dc.DuctusRenderingEngine.createStrokedShape中(DuctusRenderingEngine.java:108)
位于java.awt.BasicStroke.createStrokedShape(BasicStroke.java:301)
位于org.apache.batik.gvt.StrokeShapePainter.getPaintedArea(StrokeShapePainter.java:125)
位于org.apache.batik.gvt.StrokeShapePainter.getPaintedBounds2D(StrokeShapePainter.java:134)
位于org.apache.batik.gvt.CompositeShapePainter.getPaintedBounds2D(CompositeShapePainter.java:156)
位于org.apache.batik.gvt.ShapeNode.getPrimitiveBounds(ShapeNode.java:238)
位于org.apache.batik.gvt.AbstractGraphicsNode.getTransformedPrimitiveBounds(AbstractGraphicsNode.java:854)
位于org.apache.batik.gvt.AbstractGraphicsNode.getTransformedBounds(AbstractGraphicsNode.java:820)
位于org.apache.batik.gvt.CompositeGraphicsNode.getPrimitiveBounds(CompositeGraphicsNode.java:224)
位于org.apache.batik.gvt.CompositeGraphicsNode.getTransformedPrimitiveBounds(CompositeGraphicsNode.java:295)
位于org.apache.batik.gvt.AbstractGraphicsNode.getTransformedBounds(AbstractGraphicsNode.java:820)
位于org.apache.batik.gvt.CompositeGraphicsNode.getPrimitiveBounds(CompositeGraphicsNode.java:207)
位于org.apache.batik.gvt.AbstractGraphicsNode.getBounds(AbstractGraphicsNode.java:768)
位于org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:443)
在com.purplefrog.batikExperiment.ToPixels.renderTo(ToPixels.java:49)上
由于E_net4提出了这个问题可能是由核心调用之外的因素引起的,因此我提供了更完整的源代码:
main.rs:
use jni::{InitArgsBuilder, JNIVersion, JavaVM, AttachGuard, JNIEnv};
use jni::objects::{JValue, JObject, AutoLocal};
fn main() -> Result<(), jni::errors::Error>
{
let jvm_args = InitArgsBuilder::new()
.version(JNIVersion::V8)
.option("-Xcheck:jni")
.option(&format!("-Djava.class.path={}", heinous_classpath()))
.build()
.expect("impossible, failed to construct JVM initialization args");
let jvm:JavaVM = JavaVM::new(jvm_args)?;
let env:AttachGuard = jvm.attach_current_thread()?;
let je:&JNIEnv = &env; // this is just so intellij's larval rust plugin can give me method name completion
let cls = je.find_class("com/purplefrog/batikExperiment/ToPixels")?;
je.exception_check()?;
let width = 400;
let height = 400;
let rgbs = AutoLocal::new(&je,
JObject::from(je.new_byte_array(width*height*3)? ) );
je.exception_check()?;
println!("before calling renderTo()");
let result = je.call_static_method(cls, "renderTo", "(II[B)V", &[
JValue::from(width),
JValue::from(height),
JValue::from(rgbs.as_obj()),
])?;
je.exception_check()?;
println!("{:?}", result);
let blen = je.get_array_length(*rgbs.as_obj())? as usize;
je.exception_check()?;
let mut rgbs3:Vec<i8> = vec![0; blen];
println!("byte array length = {}", blen);
je.get_byte_array_region(*rgbs.as_obj(), 0, &mut rgbs3)?;
je.exception_check()?;
save_as_PPM(width, height, &rgbs3, "/tmp/x.ppm").expect("failed to save PPM");
return Ok(());
}
pub fn save_as_PPM(width: i32, height: i32, rgbs3: & Vec<i8>, file_name: &str)-> Result<(),std::io::Error>
{
use std::fs::File;
use std::path::Path;
use std::io::Write;
let mut f = File::create(Path::new(file_name))?;
f.write_all(format!("P6\n{} {} 255\n", width, height).as_bytes())?;
let tmp: &[u8] = unsafe { &*(rgbs3.as_slice() as *const _ as *const [u8]) };
f.write_all(tmp)?;
println!("wrote {}", file_name);
Ok(())
}
fn heinous_classpath() -> String
{
let x = "/home/thoth/src/batik-experiment/target/appassembler/etc\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-rasterizer/1.11/batik-rasterizer-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-svgrasterizer/1.11/batik-svgrasterizer-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-parser/1.11/batik-parser-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-awt-util/1.11/batik-awt-util-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/xmlgraphics-commons/2.3/xmlgraphics-commons-2.3.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/commons-io/commons-io/1.3.1/commons-io-1.3.1.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-xml/1.11/batik-xml-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/xml-apis/xml-apis-ext/1.3.04/xml-apis-ext-1.3.04.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-transcoder/1.11/batik-transcoder-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-anim/1.11/batik-anim-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-css/1.11/batik-css-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-ext/1.11/batik-ext-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-svg-dom/1.11/batik-svg-dom-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-bridge/1.11/batik-bridge-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-script/1.11/batik-script-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-dom/1.11/batik-dom-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/xalan/xalan/2.7.2/xalan-2.7.2.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/xalan/serializer/2.7.2/serializer-2.7.2.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/xml-apis/xml-apis/1.3.04/xml-apis-1.3.04.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-gvt/1.11/batik-gvt-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-svggen/1.11/batik-svggen-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-util/1.11/batik-util-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-constants/1.11/batik-constants-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-i18n/1.11/batik-i18n-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-codec/1.11/batik-codec-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/com/purplefrog/penrose/1.0-SNAPSHOT/penrose-1.0-SNAPSHOT.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/com/purplefrog/knotwork/1.0-SNAPSHOT/knotwork-1.0-SNAPSHOT.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/com/purplefrog/batikExperiment/batikExperiment/1.0-SNAPSHOT/batikExperiment-1.0-SNAPSHOT.jar";
return String::from(x);
}
使用jni:{InitArgsBuilder,JNIVersion,JavaVM,AttachGuard,JNIEnv};
使用jni::objects::{JValue,JObject,autoloc};
fn main()->结果
{
让jvm_args=InitArgsBuilder::new()
.version(JNIVersion::V8)
.option(“-Xcheck:jni”)
.option(&format!(“-Djava.class.path={}”,henious_classpath()))
.build()
.expect(“不可能,无法构造JVM初始化参数”);
让jvm:JavaVM=JavaVM::new(jvm_args)?;
让env:AttachGuard=jvm.attach_current_thread()?;
让je:&JNIEnv=&env;//这正是intellij的幼虫锈菌插件可以给我方法名的原因
设cls=je.find_class(“com/purplefrog/batikExperiment/ToPixels”)?;
je.异常检查()?;
宽度=400;
设高度=400;
设rgbs=autoloc::new(&je),
JObject::from(je.new_byte_数组(宽度*高度*3)?);
je.异常检查()?;
println!(“调用renderTo()之前”);
让result=je.调用静态方法(cls,“renderTo”,“II[B)V”&[
JValue::from(宽度),
JValue::from(高度),
JValue::from(rgbs.as_obj()),
])?;
je.异常检查()?;
println!(“{:?}”,结果);
设blen=je.get_数组_长度(*rgbs.as_obj())?as usize;
je.异常检查()?;
让mut rgbs3:Vec=Vec![0;blen];
println!(“字节数组长度={}”,blen);
je.get_byte_array_region(*rgbs.as_obj()、0和mut rgbs3)?;
je.异常检查()?;
保存为PPM(宽度、高度和rgbs3,“/tmp/x.PPM”)。预期(“保存PPM失败”);
返回Ok(());
}
发布fn另存为PPM(宽度:i32,高度:i32,rgbs3:&Vec,文件名:&str)->结果
{
使用std::fs::File;
使用std::path::path;
使用std::io::Write;
让mut f=File::create(路径::new(文件名))?;
f、 写入所有(格式!(“P6\n{}{}255\n”,宽度,高度).as_bytes())?;
设tmp:&[u8]=unsafe{&*(rgbs3.as_slice()as*const u as*const[u8]);
f、 全部写入(tmp)?;
println!(“写入{}”,文件名);
好(())
}
fn henious_classpath()->字符串
{
让x=“/home/thoth/src/batik实验/target/appassembler/etc\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-rasterizer/1.11/batik-rasterizer-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-svgrasterizer/1.11/batik-svgrasterizer-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-parser/1.11/batik-parser-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-awt-util/1.11/batik-awt-util-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/xmlgraphics-commons/2.3/xmlgraphics-commons-2.3.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/commons-io/commons-io/1.3.1/commons-io-1.3.1.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-xml/1.11/batik-xml-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/xml-api/xml-api-ext/1.3.04/xml-api-ext-1.3.04.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-transcoder/1.11/batik-transcoder-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-anim/1.11/batik-anim-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-css/1.11/batik-css-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-ext/1.11/batik-ext-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-svg-dom/1.11/batik-svg-dom-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-bridge/1.11/batik-bridge-1.11.jar\
:/home/thoth/src/batik-experiment/target/appassembler/repo/org/apache/xmlgraphics/batik-script/1.11/batik-script-1.11.jar\
:/h
[package]
name = "rust_call_jni"
version = "0.1.0"
authors = ["Robert Forsman <git@thoth.purplefrog.com>"]
edition = "2018"
[dependencies.jni]
version="0.12.3"
features=["invocation"]
package com.purplefrog.batikExperiment;
import org.apache.batik.anim.dom.*;
import org.apache.batik.bridge.*;
import org.apache.batik.gvt.*;
import org.apache.batik.gvt.renderer.*;
import org.apache.batik.util.*;
import org.w3c.dom.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.color.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.util.List;
public class ToPixels
{
public static void main(String[] args)
throws IOException
{
Document document = ultraflower();
// create the GVT
GraphicsNode gn = parseSVG(document);
BufferedImage bi = renderImageTest1(gn);
ImageIO.write(bi, "PNG", new File("/tmp/x.png"));
}
public static void renderTo(int width, int height, byte[] rgbPixels)
{
System.out.println("renderTo");
try {
List<GraphicsNode> gns = sampleGN1();
System.out.println("graphics node "+gns);
BufferedImage bi = rgbToWritableRaster(width, height, rgbPixels);
System.out.println("BufferedImage "+bi);
Graphics2D g = bi.createGraphics();
System.out.println(g);
double s = width / 1920.;
g.scale(s, s);
g.translate(0, (height/s-1080)/2.0);
for (Object child : gns) {
((GraphicsNode) child).paint(g);
}
System.out.println("painted");
} catch (IOException e) {
e.printStackTrace();
}
}
public static BufferedImage rgbToWritableRaster(int width, int height, byte[] rgbPixels)
{
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
new int[] {8,8,8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
System.out.println("ColorModel "+cm);
System.out.println(rgbPixels.length +" vs "+(width*height*3));
DataBuffer buffer = new DataBufferByte(rgbPixels, width*height*3);
System.out.println("databuffer "+buffer);
WritableRaster wr = Raster.createWritableRaster(cm.createCompatibleSampleModel(width, height), buffer, new Point());
System.out.println("writableraster "+wr);
return new BufferedImage(cm, wr, false, null);
}
public static class Exp2 {
public static void main(String[] args)
throws IOException
{
int width = 400;
int height = 600;
byte[] rgbs = new byte[width * height *3];
renderTo(width, height, rgbs);
String fname = "/tmp/x.ppm";
OutputStream ostr = new FileOutputStream(fname);
ostr.write(("P6\n"+width+" "+height+" 255\n").getBytes());
ostr.write(rgbs);
ostr.close();
}
}
public static List<GraphicsNode> sampleGN1()
throws IOException
{
GraphicsNode gn = parseSVG(ultraflower());
CanvasGraphicsNode canvas = (CanvasGraphicsNode) gn.getRoot().getChildren().get(0);
return canvas.getChildren();
}
public static BufferedImage renderImageTest1(GraphicsNode gn)
{
BufferedImage bi;
if (false) {
StaticRenderer sr = new StaticRenderer();
sr.setTree(gn);
bi = sr.getOffScreen();
} else {
bi = new BufferedImage(400,400, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
if (false) {
g.scale(0.25, 0.25);
gn.paint(g);
} else {
RootGraphicsNode rootGN = (RootGraphicsNode) gn;
rootGN.getChildren();
CanvasGraphicsNode canvasGN = (CanvasGraphicsNode) rootGN.getChildren().get(0);
double s = 400 / 1920.;
if (false) {
AffineTransform at = new AffineTransform(s, 0, 0, s, 0, 0);
//canvasGN.setViewingTransform(at);
canvasGN.setPositionTransform(at);
canvasGN.paint(g);
// this appears to clip according to the viewBox
} else {
g.scale(s, s);
g.translate(0, (1920-1080)/2.0);
for (Object child : canvasGN.getChildren()) {
((GraphicsNode) child).paint(g);
}
}
}
}
return bi;
}
public static GraphicsNode parseSVG(Document document)
{
UserAgent userAgent = new UserAgentAdapter();
DocumentLoader loader = new DocumentLoader(userAgent);
BridgeContext bctx = new BridgeContext(userAgent, loader);
bctx.setDynamicState(BridgeContext.STATIC);
GVTBuilder builder = new GVTBuilder();
return builder.build(bctx, document);
}
public static Document ultraflower()
throws IOException
{
String fname = "/home/thoth/art/ultraflower/ultraflower3.svg";
// create the document
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
return f.createDocument(fname, new FileInputStream(fname));
}
public static class Madness1
{
public static void main(String[] args)
throws IOException
{
String resource = "example1.svg";
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
Document doc = f.createDocument(resource, Madness1.class.getResourceAsStream(resource));
GraphicsNode gn = parseSVG(doc);
RootGraphicsNode rootGN = (RootGraphicsNode)gn;
CanvasGraphicsNode canvasGN = (CanvasGraphicsNode) rootGN.getChildren().get(0);
CompositeGraphicsNode gn1 = (CompositeGraphicsNode) canvasGN.getChildren().get(1);
System.out.println(gn1.getOutline());
}
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.purplefrog.batikExperiment</groupId>
<artifactId>batikExperiment</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>batikExperiment</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<programs>
<program>
<mainClass>com.purplefrog.batikExperiment.PathConverter</mainClass>
<id>pathConverter</id>
</program>
</programs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-rasterizer</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>com.purplefrog</groupId>
<artifactId>penrose</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
WARNING in native method: JNI call made without checking exceptions when required to from CallStaticVoidMethod
at sun.awt.X11.XToolkit.waitForEvents(Native Method)
at sun.awt.X11.XToolkit.run(XToolkit.java:574)
at sun.awt.X11.XToolkit.run(XToolkit.java:538)
at java.lang.Thread.run(Thread.java:748)
pub fn jvm8_args_with_classpath(classpath: &&str) -> InitArgs {
let jvm_args = InitArgsBuilder::new()
.version(JNIVersion::V8)
.option("-Xcheck:jni")
.option(&format!("-Djava.class.path={}", classpath))
.option("-Djava.awt.headless=true")
.build()
.expect("impossible, failed to construct JVM initialization args");
jvm_args
}