我有一个客户端服务器架构的应用程序.客户端使用Java Web Start和Java Swing/AWT,sert使用HTTP服务器/ Servlet和Tomcat.通信是从对象的序列化中创建的,创建一个ObjectOutput序列化一个字节数组并分别发送到服务器并调用ObjectInputStream并反序列化.
应用程序遵循正确的并发通信时间,并开始显示错误"SocketException read timeout".当服务器在我的servlet doPost方法中调用方法ObjectInputStream.getObject()时,会发生错误.
tomcat将变慢并且错误开始减少服务器响应时间,直到我必须重新启动服务器并且一切正常后的崩溃时间.
有人经历过这个问题吗?
客户代码
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(os);
oss.writeUTF("protocol header sample");
oss.writeObject(_parameters);
oss.flush();
oss.close();
Run Code Online (Sandbox Code Playgroud)
服务器代码
ObjectInputStream input = new ObjectInputStream(_request.getInputStream());
String method = input.readUTF();
parameters = input.readObject();
Run Code Online (Sandbox Code Playgroud)
input.readObject()是错误的位置
我正在为Android手机编写多人游戏.通过蓝牙进行通信.我已设法使用输入/输出流将字节从一个电话发送到另一个电话.因为我需要能够传输我想要的对象流的对象.但是,当我尝试使用我的流创建一个Objectstream时,我的程序挂起了指令.
public class ConnectedThread extends Thread {
private static final String TAG = "Connected Thread";
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private Handler mHandler;
private ObjectInputStream ois;
private ObjectOutputStream oos;
public ConnectedThread(BluetoothSocket socket,Handler h) {
mmSocket = socket;
mHandler = h;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} …Run Code Online (Sandbox Code Playgroud) 我在Android中遇到StrictMode报告的以下违规行为.
02-05 04:07:41.190:ERROR/StrictMode(15093):在附加堆栈跟踪处获取资源但从未释放.有关避免资源泄漏的信息,请参阅java.io.Closeable.02-05 04:07:41.190:ERROR/StrictMode(15093):java.lang.Throwable:未调用显式终止方法'close'
关于不正确关闭流是很困难的.但是,不应该关闭in底层流?标记错误的原因是什么?
private ArrayList<Uri> loadPath() {
ArrayList<Uri> uris = new ArrayList<Uri>();
if (mFile.exists()) {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new BufferedInputStream(
new FileInputStream(mFile), STREAM_BUFFER_SIZE));
ArrayList<String> strings = new ArrayList<String>();
strings.addAll((ArrayList<String>) in.readObject());
for (String string : strings) {
uris.add(Uri.parse(string));
}
} catch (Exception e) {
mFile.delete();
} finally {
IOUtils.closeQuietly(in);
}
}
return uris;
}
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
} …Run Code Online (Sandbox Code Playgroud) public class SerProg {
static ServerSocket ser=null;
static Socket cli=null;
static ObjectInputStream ins=null;
static ObjectOutputStream outs=null;
public static void main(String[] args) {
try {
ser=new ServerSocket(9000,10);
cli=ser.accept();
System.out.println("Connected to :"+cli.getInetAddress().getHostAddress()+" At Port :"+cli.getLocalPort());
ins=new ObjectInputStream(cli.getInputStream());
outs=new ObjectOutputStream(cli.getOutputStream());
String str=(String)ins.readObject();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
和客户
public class SerProg {
/**
* @param args
*/
static ServerSocket ser=null;
static Socket cli=null;
static ObjectInputStream ins=null;
static ObjectOutputStream outs=null;
public static void main(String[] args) …Run Code Online (Sandbox Code Playgroud) 我只是从一本java书中学习网络,所以我有点像菜鸟.我无法在书中或网上找到这个问题所以我决定问互联网.
该书说使用ObjectOutputStream和ObjectInputStream来发送和接收不同控制台的对象.
现在,我能够成功接收我发送的对象 - 但只能接收一次.当我发送不同的对象:随机字符串和整数和无名实例时,控制台具有所有正确的字段.但是当我发送一个对象的实例时,更改其中一个实例的字段的值,然后重新发送该对象,然后inpustream会加载原始实例的值.
所以,例如,我有一个类的实例,其公共int"var"等于1.如果我发送此类的实例,客户端会收到它并正确报告var = 1.但是,如果我更改var到2(在同一个实例中)并重新发送它,客户端将完成调用read()方法(因此它必须已经接收到新对象!),但它会将var报告为1.如果我将实例发送到一个尚未收到实例的不同客户端,它会正确地将var报告为2,即使我更改了var,它也会继续将其报告为2.
如果客户端之前没有收到该实例的正确版本,则该事实必须意味着该对象正在通过输出流正确发送; 由于某种原因,输入流不起作用.它几乎就像它看到它是同一个对象所以它假定它具有相同的值而不进行检查.为什么会发生这种情况,我该如何解决?
对不起,如果我问一些愚蠢的东西 - 这本书没有解释序列化和套接字如何工作,只是如何使用它们,所以我很可能从根本上对如何使用它们感到困惑.谢谢!
我编写的用于测试问题的简单代码:
服务器:(有一个计时器动作来继续发送更新的对象)
public void actionPerformed(ActionEvent e)
{
object.var++;
output.write(object);
output.flush();
System.out.println(object.var);
}
Run Code Online (Sandbox Code Playgroud)
客户
public void run()
{
while(true)
{
Test t = (Test)input.readObject();
System.out.println(t.var);
}
}
Run Code Online (Sandbox Code Playgroud)
当这些程序运行时,Server类的输出是1,2,3,4 ......无限增加,而Client的输出只有1,1,1,1,1,1,1等.
感谢您抽出时间来阅读.对不起,如果我只是愚蠢,我是这个东西的新手.
编辑:对不起,read()是一个错误的类型(我手动输入代码因为我无法正确格式化),我的意思是input.readObject()
我现在感觉非常愚蠢......我基本上是在本地机器上通过TCP连接...当我尝试在客户端进行输入/输出流时,它不会通过创建对象输入流.是什么赋予了?打印后停止2 ...没有例外或任何事情......这不是我第一次使用这个课程,这也是我困惑的原因.
try {
System.out.println("1");
mySocket = new Socket("localhost", 11311);
System.out.println("12");
oos = new ObjectOutputStream(mySocket.getOutputStream());
System.out.println("2");
ois = new ObjectInputStream(mySocket.getInputStream());
System.out.println("13");
} catch (Exception e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud) 此SocketException在ObjectInputStream.readObject()方法中引发,这是什么原因引起的呢?此外,客户端和服务器套接字的soTimeout值均为0,而KeepAlive值为false。
{2012-01-09 17:44:13,908} ERROR java.net.SocketException: Connection timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:146)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:312)
at sun.security.ssl.InputRecord.read(InputRecord.java:350)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:809)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:766)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2265)
at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2558)
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2568)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1314)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
Run Code Online (Sandbox Code Playgroud)
从有关setSoTimeout方法的JAVA API文档中,如果此方法设置为非零值,则当时间到期时,仅引发SocketTimeoutException,而不引发SocketException:Connection超时,因此,此异常不应与setSotimeoutMethod相关。
public void setSoTimeout(int timeout) throws SocketException
Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this
option set to a non-zero timeout, a read() call on the InputStream associated with
this Socket will block for only this amount of time. If the timeout …Run Code Online (Sandbox Code Playgroud) 我有一个巨大的文件,其中包含ObjectOutputStream一个接一个地写入的对象列表.
for (Object obj : currentList){
oos.writeUnshared(obj);
}
Run Code Online (Sandbox Code Playgroud)
现在我想使用ObjectInputStream读取此文件.但是,我需要同时读取多个文件,因此我无法将整个文件读入内存.但是,使用ObjectInputStream会导致堆内存不足错误.从我读到的,这是因为ObjectInputStream有内存泄漏并且即使在返回它们之后也维护对read对象的引用.
我如何要求ObjectInputStream不保持其读取的引用?
Java ObjectInputStream中有两个类似的方法:
和
文档指出:
public Object readUnshared() throws IOException, ClassNotFoundException从 ObjectInputStream 读取“非共享”对象。此方法与 readObject 相同,只不过它阻止对 readObject 和 readUnshared 的后续调用返回对通过此调用获得的反序列化实例的其他引用。具体来说:
如果调用 readUnshared 来反序列化反向引用(之前已写入流的对象的流表示形式),则会抛出 ObjectStreamException。
如果 readUnshared 成功返回,则任何后续尝试反序列化对 readUnshared 反序列化的流句柄的反向引用都将导致抛出 ObjectStreamException。
通过 readUnshared 反序列化对象会使与返回的对象关联的流句柄无效。请注意,这本身并不总是保证 readUnshared 返回的引用是唯一的;反序列化对象可以定义一个 readResolve 方法,该方法返回对其他方可见的对象,或者 readUnshared 可以返回可在流中的其他位置或通过外部方式获取的 Class 对象或枚举常量。如果反序列化对象定义了 readResolve 方法并且调用该方法返回一个数组,则 readUnshared 返回该数组的浅表克隆;这保证了返回的数组对象是唯一的,并且无法通过对 ObjectInputStream 调用 readObject 或 readUnshared 再次获取,即使底层数据流已被操作。
重写此方法的 ObjectInputStream 子类只能在拥有“enableSubclassImplementation”SerializedPermission 的安全上下文中构造;任何在没有此权限的情况下实例化此类子类的尝试都将导致抛出 SecurityException。
但我想知道是否有人在现实生活中对此有.readUnshared()用途.readObject()
ObjectInputStream.readFields()仅在private void readObject(ObjectInputStream)方法内有资格.
public ObjectInputStream.GetField readFields() throws IOException, ClassNotFoundException {
SerialCallbackContext ctx = curContext;
if (ctx == null) {
throw new NotActiveException("not in call to readObject");
}
...
Run Code Online (Sandbox Code Playgroud)
当我无法使用默认序列化来读取对象(即ObjectInputStream.defaultReadObject())并且不希望readObject()在我的所有类中实现方法时,我处于这种情况.在理想情况下,我希望有一个 ownDefaultReadObject()方法可以从序列化字段构建新对象(例如通过反射).
有任何想法吗?
如果有人想知道更多.我的一些类中的字段名称被重命名(例如通过混淆器)到a,b,c等.这些类使用默认的Java序列化使用重命名的字段进行序列化.我需要将它们反序列化为原始类(我知道每个类的字段名称对; a => fieldName,b => age,c => gender等).
java obfuscation serialization objectinputstream deserialization
java ×9
sockets ×4
android ×2
bluetooth ×1
java-7 ×1
memory-leaks ×1
obfuscation ×1
oracle ×1
tcp ×1
tomcat ×1