Tôi đã có một vấn đề tương tự chỉ là bây giờ sử dụng một Applet trong Google Chrome.
Nói tóm lại:
- Các chủ đề BLOCKED có thể bị chặn khi VM cần nạp một lớp.
- Khi quá trình tải bản thân lớp bị chặn bởi một thứ gì đó bị đóng băng cho toàn bộ ứng dụng có thể xảy ra.
Trong Xem chi tiết:
tôi đã có tình huống sau:
- Tôi đang sử dụng một Applet trong Chrome với codebase = thư mục để đơn đẳng cấp file (không jar)
- Trang web chuyển các sự kiện trọng tâm tới applet bằng LiveConnect
- Các cuộc gọi JS đến đang sử dụng
Executor
với new Runnable() ...
để de tach các cuộc gọi để giảm thời gian chờ đợi và do đó bị treo trong JS.
- Đó là nơi xảy ra sự cố!
Giải thích:
- Các
new Runnable()
là một lớp bên trong annonymous mà đã không được nạp trước khi cuộc gọi JS xảy ra.
- Cuộc gọi JS do đó kích hoạt tải lớp.
- Nhưng bây giờ trình nạp lớp bị chặn vì nó cần nói chuyện với trình duyệt (tôi đoán) thông qua cùng một hàng đợi hoặc cơ chế đang xử lý cuộc gọi JS đến.
Đây là chủ đề bị chặn mà đang cố gắng tải các lớp:
"Thread-20" daemon prio=4 tid=0x052e8400 nid=0x4608 in Object.wait() [0x0975d000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at sun.plugin2.message.Queue.waitForMessage(Unknown Source)
- locked <0x29fbc5d8> (a sun.plugin2.message.Queue)
at sun.plugin2.message.Pipe$2.run(Unknown Source)
at com.sun.deploy.util.Waiter$1.wait(Unknown Source)
at com.sun.deploy.util.Waiter.runAndWait(Unknown Source)
at sun.plugin2.message.Pipe.receive(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.doCookieOp(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.getCookie(Unknown Source)
at sun.plugin2.main.client.PluginCookieSelector.getCookieFromBrowser(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.getCookieInfo(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.get(Unknown Source)
- locked <0x298da868> (a sun.plugin2.main.client.PluginCookieSelector)
at sun.net.www.protocol.http.HttpURLConnection.setCookieHeader(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.writeRequests(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
- locked <0x2457cdc0> (a sun.net.www.protocol.http.HttpURLConnection)
at com.sun.deploy.net.HttpUtils.followRedirects(Unknown Source)
at com.sun.deploy.net.BasicHttpRequest.doRequest(Unknown Source)
at com.sun.deploy.net.BasicHttpRequest.doGetRequestEX(Unknown Source)
at com.sun.deploy.cache.ResourceProviderImpl.checkUpdateAvailable(Unknown Source)
at com.sun.deploy.cache.ResourceProviderImpl.isUpdateAvailable(Unknown Source)
at com.sun.deploy.cache.DeployCacheHandler.get(Unknown Source)
- locked <0x245727a0> (a java.lang.Object)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
- locked <0x24572020> (a sun.net.www.protocol.http.HttpURLConnection)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.getBytes(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.access$000(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
- locked <0x299726b8> (a sun.plugin2.applet.Applet2ClassLoader)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
- locked <0x299726b8> (a sun.plugin2.applet.Applet2ClassLoader)
at java.lang.ClassLoader.loadClass(Unknown Source)
Như bạn có thể nhìn thấy nó đang chờ đợi một tin nhắn ->waitForMessage()
.
Đồng thời có JS cuộc gọi đến của chúng tôi bị chặn ở đây:
"Applet 1 LiveConnect Worker Thread" prio=4 tid=0x05231800 nid=0x1278 waiting for monitor entry [0x0770e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at MyClass.myMethod(MyClass.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin.javascript.Trampoline.invoke(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke0(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInvocationDelegate.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$LiveConnectWorker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
bổ sung chủ đề khác đã bị chặn theo cách tương tự. Tôi cho rằng tất cả các yêu cầu tải lớp tiếp theo đã bị chặn bởi chuỗi tải lớp bị chặn đầu tiên.
Như đã đề cập trước đây, tôi đoán là quá trình tải lớp bị chặn bởi cuộc gọi JS đang chờ xử lý, mà chính nó bị chặn bởi lớp bị thiếu sẽ được tải.
Giải pháp:
- Kích hoạt tải tất cả các lớp học có liên quan trong constructor của applet trước bất kỳ cuộc gọi có thể được thực hiện từ JS.
- Nó có thể giúp đỡ nếu các tập tin lớp học không được tải riêng lẻ, nhưng từ một tập tin jar. Lý thuyết đằng sau này là: Trình nạp lớp không cần nói chuyện với trình duyệt để tải các lớp từ tệp jar (sẽ là
- Kết hợp với 1 .: Sử dụng lớp động Proxy để bao bọc tất cả các cuộc gọi JS đến và chạy chúng một cách độc lập trong một Executor
thực hiện của tôi cho # 3:
public class MyClass implements JsCallInterface
{
private final JsCallInterface jsProxy;
private final static interface JsCallInterface
{
public void myMethod1Intern(String param1, String param2);
}
private final class JsCallRunnable implements Runnable
{
private final Method method;
private final Object[] args;
private JsCallRunnable(Method method, Object[] args)
{
this.method = method;
this.args = args;
}
public void run()
{
try
{
method.invoke(MyClass.this, args);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public MyClass()
{
MyUtilsClass.class.getName(); // load class
JsCallRunnable.class.getName(); // load class
InvocationHandler jsCallHandler = new InvocationHandler()
{
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable
{
MyUtilsClass.executeInExecutor(new JsCallRunnable(method, args));
return null;
}
};
jsProxy = (JsCallInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(), new Class<?>[] { JsCallInterface.class }, jsCallHandler);
}
public void myMethod1(String param1, String param2)
{
jsProxy.myMethod1Intern(param1, param2);
// needs to be named differently than the external method or else the proxy will call this method recursively
// alternatively the target-class in "method.invoke(MyClass.this, args);" could be a different instance of JsCallInterface
}
public void myMethod1Intern(String param1, String param2)
{
// do actual work here
}
}
Bạn có thấy bất kỳ mục nhập nào khác để tham chiếu 0x00000000472bc000 không? –
Không, không phải trong cùng một bãi chứa. 0x00000000472bc000 xác định chuỗi "TP-Processor75", vì vậy bạn có mong đợi nhiều đề cập của cùng một chuỗi trong kết xuất không? – Oliver
Vâng 0x00000000472bc000 cho biết màn hình đang chờ để vào. Đó là một luồng khác đã nhập tham chiếu màn hình 0x00000000472bc000 và TP-Processor75 đang chờ chuỗi đang giữ để giải phóng 0x00000000472bc000 –