是否有Java的析构函数?我似乎无法找到任何关于此的文档.如果没有,我怎样才能达到同样的效果?
为了使我的问题更具体,我正在编写一个处理数据的应用程序,并且规范说应该有一个"重置"按钮,使应用程序恢复到其原始的刚启动状态.但是,除非关闭应用程序或按下重置按钮,否则所有数据都必须为"实时".
作为一名C/C++程序员,我认为实现这一点非常简单.(因此我计划最后实现它.)我构建了我的程序,使得所有'可重置'对象都在同一个类中,这样我就可以在按下重置按钮时销毁所有'实时'对象.
我在想如果我所做的只是取消引用数据并等待垃圾收集器收集它们,如果我的用户反复输入数据并按下重置按钮,是否会出现内存泄漏?我也在想,因为Java作为一种语言非常成熟,应该有办法防止这种情况发生或优雅地解决这个问题.
我有一个文件的InputStream,我使用apache poi组件来读取它像这样:
POIFSFileSystem fileSystem = new POIFSFileSystem(inputStream);
Run Code Online (Sandbox Code Playgroud)
问题是我需要多次使用相同的流,POIFSFileSystem在使用后关闭流.
从输入流缓存数据然后将更多输入流提供给不同的POIFSFileSystem的最佳方法是什么?
编辑1:
通过缓存我的意思是存储供以后使用,而不是作为加速应用程序的方法.最好是将输入流读入数组或字符串,然后为每次使用创建输入流?
编辑2:
很抱歉重新打开这个问题,但在桌面和Web应用程序中工作时条件有所不同.首先,我从tomcat web app中的org.apache.commons.fileupload.FileItem获取的InputStream不支持标记,因此无法重置.
其次,我希望能够将文件保存在内存中,以便在处理文件时更快地访问和减少io问题.
我们最近将我们的消息处理应用程序从Java 7升级到Java 8.自升级以来,我们偶尔会遇到一个流在读取时被关闭的异常.记录显示终结器线程正在调用finalize()保存流的对象(进而关闭流).
代码的基本概要如下:
MIMEWriter writer = new MIMEWriter( out );
in = new InflaterInputStream( databaseBlobInputStream );
MIMEBodyPart attachmentPart = new MIMEBodyPart( in );
writer.writePart( attachmentPart );
Run Code Online (Sandbox Code Playgroud)
MIMEWriter并且MIMEBodyPart是本土MIME/HTTP库的一部分. MIMEBodyPart扩展HTTPMessage,具有以下内容:
public void close() throws IOException
{
if ( m_stream != null )
{
m_stream.close();
}
}
protected void finalize()
{
try
{
close();
}
catch ( final Exception ignored ) { }
}
Run Code Online (Sandbox Code Playgroud)
异常发生在调用链中MIMEWriter.writePart,如下所示:
MIMEWriter.writePart() 写入部件的标题,然后调用 part.writeBodyPartContent( this )MIMEBodyPart.writeBodyPartContent()调用我们的实用工具方法 …这主要是出于好奇.
如果有人遇到Object.finalize()的任何良好用法,除了调试/记录/分析目的外,我还在徘徊?
如果你没有遇到任何你会说好的用法会是什么?
有没有办法创建一个处理程序,在最后一次释放某个对象的时候,它将被完全调用?
一个示例是由物理数据文件支持的对象,一旦对象变为未引用,该文件应该被关闭而不是重命名.如果没有在该对象上显式调用"close"方法,那将是很好的.
我从Weak/Phantom参考区域了解到的所有通知机制仅表明通知将在某个时间点发生,但是没有保证何时会发生这种情况......
我有一个课程,一方面,InputStream从公共方法返回一个感觉是正确的,例如
public class MyClass {
private File _file;
...
public InputStream getInputStream() {
return new FileInputStream( _file );
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我对这样做也非常谨慎,因为它让调用者有责任关闭这个流.我有什么方法可以避免这个问题?
我想在C中分配一些内存并使其与java对象实例相关联,如下所示:
void configure(JNIEnv *object, jobject obj, ....) {
char *buf = new char[1024];
// associated <buf> with <obj> somehow
}
Run Code Online (Sandbox Code Playgroud)
然后在java对象被垃圾收集时释放内存 - 我可以通过从java对象的finalize()方法调用JNI函数来实现.
问题是,如何将C指针与java对象相关联?在对象中保留一个长字段并将指针强制转换为长?有没有更好的办法?
可能重复:
为什么要实现finalize()?
我看到一些带有以下代码的java文件:
public void finalize() {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
Connection的finalize方法最好的做法?Connection或需要关闭其他对象,如PreparedStatement?乍一看,Python的__del__特殊方法似乎提供了析构函数在C++中具有的相同优势.但是根据Python文档(https://docs.python.org/3.4/reference/datamodel.html),无法保证您的对象的__del__方法完全被调用!
无法保证
__del__在解释器退出时仍然存在的对象调用()方法.
换句话说,这个方法没用!不是吗?可能会或可能不会被调用的钩子函数确实没有多大好处,因此__del__对RAII没有任何帮助.如果我有一些必要的清理,我不需要它运行一些时间,哦,当GC感觉它真的,我需要它可靠,确定和100%的时间运行.
我知道Python提供了上下文管理器,它对于该任务更有用,但为什么要__del__保持原样呢?重点是什么?
当我使用JNI方法构建java对象时,为了将其作为参数传递给我正在使用JNI调用API调用的java方法,我该如何管理它的内存?
这是我正在使用的:
我有一个C对象,它有一个更复杂的析构函数方法free().这个C对象与Java对象相关联,一旦应用程序完成Java对象,我就不再需要C对象了.
我正在创建这样的Java对象(为了清楚起见,错误检查已被省略):
c_object = c_object_create ();
class = (*env)->FindClass (env, "my.class.name");
constructor = (*env)->GetMethodID (env, class, "<init>", "(J)V");
instance = (*env)->NewObject (env, class, constructor, (jlong) c_object);
method = (*env)->GetMethodID (env, other_class, "doSomeWork", "(Lmy.class.name)V");
(*env)->CallVoidMethod (env, other_class, method, instance);
Run Code Online (Sandbox Code Playgroud)
那么,既然我已经完成了instance,我该怎么办呢?理想情况下,我想将垃圾收集器留给VM; 当它完成时instance它会很棒,如果它也调用c_object_destroy()我提供给它的指针.这可能吗?
一个单独但相关的问题与我在这样的方法中创建的Java实体的范围有关; 我必须手动释放,也就是说,class,constructor,或method以上?关于适当的内存管理问题,JNI文档令我感到沮丧(在我看来).
java ×9
finalizer ×3
c ×2
inputstream ×2
android-ndk ×1
apache-poi ×1
c++ ×1
caching ×1
destructor ×1
finalize ×1
io ×1
java-8 ×1
python ×1
raii ×1
reference ×1