Skip to content

Commit 0084673

Browse files
committed
Update FileDescriptor and I/O stream classes to use fd-based file access
1 parent 7c700e3 commit 0084673

4 files changed

Lines changed: 75 additions & 52 deletions

File tree

java_runtime/src/classes/java/io/file_descriptor.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use java_class_proto::{JavaFieldProto, JavaMethodProto};
44
use java_constants::{FieldAccessFlags, MethodAccessFlags};
55
use jvm::{ClassInstanceRef, Jvm, Result};
66

7-
use crate::{File, RuntimeClassProto, RuntimeContext};
7+
use crate::{RuntimeClassProto, RuntimeContext};
88

99
// class java.io.FileDescriptor
1010
pub struct FileDescriptor;
@@ -20,7 +20,7 @@ impl FileDescriptor {
2020
JavaMethodProto::new("<clinit>", "()V", Self::cl_init, MethodAccessFlags::STATIC),
2121
],
2222
fields: vec![
23-
JavaFieldProto::new("raw", "[B", Default::default()),
23+
JavaFieldProto::new("fd", "I", Default::default()),
2424
JavaFieldProto::new("err", "Ljava/io/FileDescriptor;", FieldAccessFlags::STATIC),
2525
JavaFieldProto::new("in", "Ljava/io/FileDescriptor;", FieldAccessFlags::STATIC),
2626
JavaFieldProto::new("out", "Ljava/io/FileDescriptor;", FieldAccessFlags::STATIC),
@@ -32,28 +32,28 @@ impl FileDescriptor {
3232
async fn cl_init(jvm: &Jvm, runtime: &mut RuntimeContext) -> Result<()> {
3333
tracing::debug!("java.io.FileDescriptor::<clinit>()");
3434

35-
let stderr_file = runtime.stderr();
36-
if let Ok(stderr_file) = stderr_file {
35+
let stderr_fd = runtime.stderr();
36+
if let Ok(stderr_fd) = stderr_fd {
3737
let mut stderr = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
38-
jvm.put_rust_object_field(&mut stderr, "raw", stderr_file).await?;
38+
jvm.put_field(&mut stderr, "fd", "I", stderr_fd.id() as i32).await?;
3939

4040
jvm.put_static_field("java/io/FileDescriptor", "err", "Ljava/io/FileDescriptor;", stderr)
4141
.await?;
4242
}
4343

44-
let stdin_file = runtime.stdin();
45-
if let Ok(stdin_file) = stdin_file {
44+
let stdin_fd = runtime.stdin();
45+
if let Ok(stdin_fd) = stdin_fd {
4646
let mut stdin = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
47-
jvm.put_rust_object_field(&mut stdin, "raw", stdin_file).await?;
47+
jvm.put_field(&mut stdin, "fd", "I", stdin_fd.id() as i32).await?;
4848

4949
jvm.put_static_field("java/io/FileDescriptor", "in", "Ljava/io/FileDescriptor;", stdin)
5050
.await?;
5151
}
5252

53-
let stdout_file = runtime.stdout();
54-
if let Ok(stdout_file) = stdout_file {
53+
let stdout_fd = runtime.stdout();
54+
if let Ok(stdout_fd) = stdout_fd {
5555
let mut stdout = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
56-
jvm.put_rust_object_field(&mut stdout, "raw", stdout_file).await?;
56+
jvm.put_field(&mut stdout, "fd", "I", stdout_fd.id() as i32).await?;
5757

5858
jvm.put_static_field("java/io/FileDescriptor", "out", "Ljava/io/FileDescriptor;", stdout)
5959
.await?;
@@ -70,14 +70,30 @@ impl FileDescriptor {
7070
Ok(())
7171
}
7272

73-
pub async fn from_file(jvm: &Jvm, file: Box<dyn File>) -> Result<ClassInstanceRef<Self>> {
73+
pub async fn from_fd(jvm: &Jvm, fd: crate::FileDescriptorId) -> Result<ClassInstanceRef<Self>> {
7474
let mut this = jvm.new_class("java/io/FileDescriptor", "()V", []).await?;
75-
jvm.put_rust_object_field(&mut this, "raw", file).await?;
75+
jvm.put_field(&mut this, "fd", "I", fd.id() as i32).await?;
7676

7777
Ok(this.into())
7878
}
7979

80-
pub async fn file(jvm: &Jvm, this: ClassInstanceRef<Self>) -> Result<Box<dyn File>> {
81-
jvm.get_rust_object_field(&this, "raw").await
80+
pub async fn file(jvm: &Jvm, runtime: &RuntimeContext, this: ClassInstanceRef<Self>) -> Result<Box<dyn crate::File>> {
81+
let fd: i32 = jvm.get_field(&this, "fd", "I").await?;
82+
if fd <= 0 {
83+
return Err(jvm.exception("java/io/IOException", "Invalid file descriptor").await);
84+
}
85+
let fd = crate::FileDescriptorId::new(fd as u32);
86+
match runtime.get_file(fd) {
87+
Ok(file) => Ok(file),
88+
Err(_) => Err(jvm.exception("java/io/IOException", "Invalid file descriptor").await),
89+
}
90+
}
91+
92+
pub async fn close(jvm: &Jvm, runtime: &RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
93+
let fd: i32 = jvm.get_field(&this, "fd", "I").await?;
94+
if fd > 0 {
95+
runtime.close_file(crate::FileDescriptorId::new(fd as u32));
96+
}
97+
Ok(())
8298
}
8399
}

java_runtime/src/classes/java/io/file_input_stream.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,12 @@ impl FileInputStream {
4343
let path = jvm.invoke_virtual(&file, "getPath", "()Ljava/lang/String;", ()).await?;
4444
let path = JavaLangString::to_rust_string(jvm, &path).await?;
4545

46-
let rust_file = context.open(&path, false).await;
47-
if rust_file.is_err() {
48-
// TODO correct error handling
46+
let fd = context.open(&path, false).await;
47+
if fd.is_err() {
4948
return Err(jvm.exception("java/io/FileNotFoundException", "File not found").await);
5049
}
5150

52-
let fd = FileDescriptor::from_file(jvm, rust_file.unwrap()).await?;
51+
let fd = FileDescriptor::from_fd(jvm, fd.unwrap()).await?;
5352

5453
let _: () = jvm
5554
.invoke_special(&this, "java/io/FileInputStream", "<init>", "(Ljava/io/FileDescriptor;)V", (fd,))
@@ -73,11 +72,11 @@ impl FileInputStream {
7372
Ok(())
7473
}
7574

76-
async fn available(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
75+
async fn available(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
7776
tracing::debug!("java.io.FileInputStream::available({:?})", &this);
7877

7978
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
80-
let rust_file = FileDescriptor::file(jvm, fd).await?;
79+
let rust_file = FileDescriptor::file(jvm, context, fd).await?;
8180

8281
// TODO get os buffer size
8382
let stat = rust_file.metadata().await.unwrap();
@@ -90,7 +89,7 @@ impl FileInputStream {
9089

9190
async fn read_array(
9291
jvm: &Jvm,
93-
_: &mut RuntimeContext,
92+
context: &mut RuntimeContext,
9493
this: ClassInstanceRef<Self>,
9594
mut buf: ClassInstanceRef<Array<i8>>,
9695
offset: i32,
@@ -99,7 +98,7 @@ impl FileInputStream {
9998
tracing::debug!("java.io.FileInputStream::read({this:?}, {buf:?}, {offset:?}, {length:?})");
10099

101100
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
102-
let mut rust_file = FileDescriptor::file(jvm, fd).await?;
101+
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
103102

104103
let mut rust_buf = vec![0; length as _];
105104
let read = rust_file.read(&mut rust_buf).await.unwrap();
@@ -112,11 +111,11 @@ impl FileInputStream {
112111
Ok(read as _)
113112
}
114113

115-
async fn read_byte(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
114+
async fn read_byte(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i32> {
116115
tracing::debug!("java.io.FileInputStream::read({:?})", &this);
117116

118117
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
119-
let mut rust_file = FileDescriptor::file(jvm, fd).await?;
118+
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
120119

121120
let mut buf = [0; 1];
122121
let read = rust_file.read(&mut buf).await.unwrap();
@@ -127,8 +126,11 @@ impl FileInputStream {
127126
Ok(buf[0] as i32)
128127
}
129128

130-
async fn close(_jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
131-
tracing::debug!("stub java.io.FileInputStream::close({:?})", &this);
129+
async fn close(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
130+
tracing::debug!("java.io.FileInputStream::close({:?})", &this);
131+
132+
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
133+
FileDescriptor::close(jvm, context, fd).await?;
132134

133135
Ok(())
134136
}

java_runtime/src/classes/java/io/file_output_stream.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ impl FileOutputStream {
4242
let path = jvm.invoke_virtual(&file, "getPath", "()Ljava/lang/String;", ()).await?;
4343
let path = JavaLangString::to_rust_string(jvm, &path).await?;
4444

45-
let file = context.open(&path, true).await.unwrap();
46-
let fd = FileDescriptor::from_file(jvm, file).await?;
45+
let fd = context.open(&path, true).await.unwrap();
46+
let fd = FileDescriptor::from_fd(jvm, fd).await?;
4747

4848
let _: () = jvm
4949
.invoke_special(&this, "java/io/FileOutputStream", "<init>", "(Ljava/io/FileDescriptor;)V", (fd,))
@@ -69,7 +69,7 @@ impl FileOutputStream {
6969

7070
async fn write_bytes_offset(
7171
jvm: &Jvm,
72-
_: &mut RuntimeContext,
72+
context: &mut RuntimeContext,
7373
this: ClassInstanceRef<Self>,
7474
buffer: ClassInstanceRef<Array<i8>>,
7575
offset: i32,
@@ -84,7 +84,7 @@ impl FileOutputStream {
8484
);
8585

8686
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
87-
let mut file = FileDescriptor::file(jvm, fd).await?;
87+
let mut file = FileDescriptor::file(jvm, context, fd).await?;
8888

8989
let mut buf = vec![0; length as _];
9090
jvm.array_raw_buffer(&buffer).await?.read(offset as _, &mut buf).unwrap();
@@ -94,19 +94,22 @@ impl FileOutputStream {
9494
Ok(())
9595
}
9696

97-
async fn write(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, byte: i32) -> Result<()> {
97+
async fn write(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>, byte: i32) -> Result<()> {
9898
tracing::debug!("java.io.FileOutputStream::write({:?}, {:?})", &this, &byte);
9999

100100
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
101-
let mut file = FileDescriptor::file(jvm, fd).await?;
101+
let mut file = FileDescriptor::file(jvm, context, fd).await?;
102102

103103
file.write(&[byte as u8]).await.unwrap();
104104

105105
Ok(())
106106
}
107107

108-
async fn close(_jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
109-
tracing::debug!("stub java.io.FileInputStream::close({:?})", &this);
108+
async fn close(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
109+
tracing::debug!("java.io.FileOutputStream::close({:?})", &this);
110+
111+
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
112+
FileDescriptor::close(jvm, context, fd).await?;
110113

111114
Ok(())
112115
}

java_runtime/src/classes/java/io/random_access_file.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,11 @@ impl RandomAccessFile {
5757

5858
let write = mode.contains('w');
5959

60-
let rust_file = context.open(&name, write).await;
61-
if rust_file.is_err() {
62-
// TODO correct error handling
60+
let fd_id = context.open(&name, write).await;
61+
if fd_id.is_err() {
6362
return Err(jvm.exception("java/io/FileNotFoundException", "File not found").await);
6463
}
65-
let fd = FileDescriptor::from_file(jvm, rust_file.unwrap()).await?;
64+
let fd = FileDescriptor::from_fd(jvm, fd_id.unwrap()).await?;
6665
jvm.put_field(&mut this, "fd", "Ljava/io/FileDescriptor;", fd).await?;
6766

6867
Ok(())
@@ -103,7 +102,7 @@ impl RandomAccessFile {
103102

104103
async fn read_offset_length(
105104
jvm: &Jvm,
106-
_: &mut RuntimeContext,
105+
context: &mut RuntimeContext,
107106
this: ClassInstanceRef<Self>,
108107
mut buf: ClassInstanceRef<Array<i8>>,
109108
offset: i32,
@@ -112,7 +111,7 @@ impl RandomAccessFile {
112111
tracing::debug!("java.io.RandomAccessFile::read({:?}, {:?}, {:?}, {:?})", &this, &buf, &offset, &length);
113112

114113
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
115-
let mut rust_file = FileDescriptor::file(jvm, fd).await?;
114+
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
116115

117116
let mut rust_buf = vec![0; length as usize];
118117
let read = rust_file.read(&mut rust_buf).await.unwrap();
@@ -133,7 +132,7 @@ impl RandomAccessFile {
133132

134133
async fn write_offset_length(
135134
jvm: &Jvm,
136-
_: &mut RuntimeContext,
135+
context: &mut RuntimeContext,
137136
this: ClassInstanceRef<Self>,
138137
buf: ClassInstanceRef<Array<i8>>,
139138
offset: i32,
@@ -142,7 +141,7 @@ impl RandomAccessFile {
142141
tracing::debug!("java.io.RandomAccessFile::write({:?}, {:?}, {:?}, {:?})", &this, &buf, &offset, &length);
143142

144143
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
145-
let mut rust_file = FileDescriptor::file(jvm, fd).await?;
144+
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
146145

147146
let mut rust_buf = vec![0; length as usize];
148147
jvm.array_raw_buffer(&buf).await?.read(offset as _, &mut rust_buf).unwrap();
@@ -151,44 +150,44 @@ impl RandomAccessFile {
151150
Ok(())
152151
}
153152

154-
async fn seek(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, pos: i64) -> Result<()> {
153+
async fn seek(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>, pos: i64) -> Result<()> {
155154
tracing::debug!("java.io.RandomAccessFile::seek({:?}, {:?})", &this, &pos);
156155

157156
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
158-
let mut rust_file = FileDescriptor::file(jvm, fd).await?;
157+
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
159158

160159
rust_file.seek(pos as _).await.unwrap();
161160

162161
Ok(())
163162
}
164163

165-
async fn set_length(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>, new_length: i64) -> Result<()> {
164+
async fn set_length(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>, new_length: i64) -> Result<()> {
166165
tracing::debug!("java.io.RandomAccessFile::setLength({:?}, {:?})", &this, &new_length);
167166

168167
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
169-
let mut rust_file = FileDescriptor::file(jvm, fd).await?;
168+
let mut rust_file = FileDescriptor::file(jvm, context, fd).await?;
170169

171170
rust_file.set_len(new_length as _).await.unwrap();
172171

173172
Ok(())
174173
}
175174

176-
async fn length(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i64> {
175+
async fn length(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i64> {
177176
tracing::debug!("java.io.RandomAccessFile::length({:?})", &this);
178177

179178
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
180-
let rust_file = FileDescriptor::file(jvm, fd).await?;
179+
let rust_file = FileDescriptor::file(jvm, context, fd).await?;
181180

182181
let len = rust_file.metadata().await.unwrap().size;
183182

184183
Ok(len as i64)
185184
}
186185

187-
async fn get_file_pointer(jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i64> {
186+
async fn get_file_pointer(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<i64> {
188187
tracing::debug!("java.io.RandomAccessFile::getFilePointer({:?})", &this);
189188

190189
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
191-
let rust_file = FileDescriptor::file(jvm, fd).await?;
190+
let rust_file = FileDescriptor::file(jvm, context, fd).await?;
192191

193192
let pos = rust_file.tell().await.unwrap();
194193

@@ -203,9 +202,12 @@ impl RandomAccessFile {
203202
Ok(fd)
204203
}
205204

206-
async fn close(_jvm: &Jvm, _: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
205+
async fn close(jvm: &Jvm, context: &mut RuntimeContext, this: ClassInstanceRef<Self>) -> Result<()> {
207206
tracing::debug!("java.io.RandomAccessFile::close({:?})", &this);
208207

208+
let fd = jvm.get_field(&this, "fd", "Ljava/io/FileDescriptor;").await?;
209+
FileDescriptor::close(jvm, context, fd).await?;
210+
209211
Ok(())
210212
}
211213
}

0 commit comments

Comments
 (0)