I am getting JVM crash issue frequently while trying to write to the Excel file.I am using Apache POI 3.12 and Java 8 and Tomcat Server.
I get the following hs_err_pid error:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGBUS (0x7) at pc=0x00007f16e02d1ec0, pid=1135, tid=0x00007f1595ef8700
#
# JRE version: OpenJDK Runtime Environment (8.0_352-b08) (build 1.8.0_352-8u352-ga-1~18.04-b08)
# Java VM: OpenJDK 64-Bit Server VM (25.352-b08 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C [libzip.so+0x4ec0]
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
------
Stack: [0x00007f1595df8000,0x00007f1595ef9000], sp=0x00007f1595ef5900, free space=1014k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libzip.so+0x4ec0]
C [libzip.so+0x5b6e]
C [libzip.so+0x3b25] Java_java_util_zip_ZipFile_getEntry+0x85
J 91 java.util.zip.ZipFile.getEntry(J[BZ)J (0 bytes) # 0x00007f16cd13ea8e [0x00007f16cd13e9c0+0xce]
J 123871 C2 java.util.zip.ZipFile.getInputStream(Ljava/util/zip/ZipEntry;)Ljava/io/InputStream; (304 bytes) # 0x00007f16d6716944 [0x00007f16d67165c0+0x384]
J 124037 C2 org.apache.poi.openxml4j.opc.PackagePart.getInputStream()Ljava/io/InputStream; (44 bytes) # 0x00007f16cda4bd00 [0x00007f16cda4bc60+0xa0]
J 103326 C1 org.apache.poi.POIXMLProperties.<init>(Lorg/apache/poi/openxml4j/opc/OPCPackage;)V (212 bytes) # 0x00007f16d6af7374 [0x00007f16d6af6300+0x1074]
J 100022 C1 org.apache.poi.POIXMLDocument.getProperties()Lorg/apache/poi/POIXMLProperties; (40 bytes) # 0x00007f16cd79ddfc [0x00007f16cd79dce0+0x11c]
J 67174 C1 org.apache.poi.POIXMLDocument.write(Ljava/io/OutputStream;)V (35 bytes) # 0x00007f16cd89404c [0x00007f16cd893a80+0x5cc]
J 65014 C1 com.bulk.helper.ExcelUtility.saveWorkBook(Lorg/apache/poi/ss/usermodel/Workbook;Ljava/lang/String;Ljava/lang/String;)V (89 bytes) # 0x00007f16cd543754 [0x00007f16cd542ea0+0x8b4]
J 71211 C1 com.bulk.helper.ExcelAccess.save_userfile(Ljava/lang/String;Ljava/lang/String;)V (14 bytes) # 0x00007f16ce6e46ec [0x00007f16ce6e4640+0xac]
J 93237 C1
The following is the code:
Calling class:
accessFile.save_newFile(---);
Common Method Class:
#Override
public void save_userfile(String filePath , String fileName) {
utility.saveWorkBook(userWorkbook,filePath,fileName);
}
public void saveWorkBook(Workbook workbook ,String filePath, String fileName){
try
{
File directory = new File(filePath);
if (!directory.exists()) {
directory.mkdir();
}
File file = new File(directory,fileName);
OutputStream out = new FileOutputStream(file);
workbook.write(out);
out.flush();
out.close();
workbook.close();
}catch(Exception e){
LOG.error(Constants.ERROR_STRING,e);
}
}
I am aware of the solution of putting "-Dsun.zip.disableMemoryMapping=true" parameter.
Enabling this option will impact performance because the VM will have to conduct some additional disk IO every time it reads an entry from a JAR file (to interrogate the central directory structure).
Want to solve this issue programmatically in java 8 itself.
Any help will be appreciated,Thanks in advance..
I don't know if there is any solution in Java 8 other the one you have already mentioned; i.e. disabling memory mapping.
However if you look at the various JDK bug reports for native code crashes in getEntry, they are marked as "resolved in Java 9". So upgrading to Java 11 is a possible solution.
In Java 9 they have replaced the native implementation of ZipFile with a pure Java implementation.
For reference, here are some of related Java bug reports against Java 8 and earlier versions:
https://bugs.openjdk.org/browse/JDK-8142508
https://bugs.openjdk.org/browse/JDK-8144958
https://bugs.openjdk.org/browse/JDK-8145260
https://bugs.openjdk.org/browse/JDK-7142247
Related
I'm trying to get into Vulkan with LWJGL.
Currently I'm creating some sort of window (wrapper) class, however whenever i try to invoke glfwGetWindowSize, glfwGetWindowPos or glfwGetMonitorPos the program crashes with a segmentation fault. The window creation itself works fine though, and i can also move the window programatically. I use default window hints (glfwDefaultWindowHints).
The code:
var wbuf = IntBuffer.allocate(1);
var hbuf = IntBuffer.allocate(1);
glfwGetWindowSize(this.handle, wbuf, hbuf);
this.width = wbuf.get();
this.height = hbuf.get();
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f29938156b5, pid=13791, tid=13797
#
# JRE version: OpenJDK Runtime Environment Temurin-17.0.5+8 (17.0.5+8) (build 17.0.5+8)
# Java VM: OpenJDK 64-Bit Server VM Temurin-17.0.5+8 (17.0.5+8, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C [libglfw.so+0x156b5] glfwGetWindowSize+0x5
Environment: LWJGL v3.3.1 (with GLFW linux natives), Vulkan SDK v1.3.236.0 x86_64, Java 17 (Temurin), Fedora 36
As a side note: I'm also applying class loader tweaks before the GLFW init.
I was using non-direct buffers, while the LWJGL GLFW bidings only support direct ones.
Using direct buffers works fine:
try (var stack = MemoryStack.stackPush()) {
var width = stack.mallocInt(1);
var height = stack.mallocInt(1);
glfwGetWindowSize(this.handle, width, height);
this.width = width.get();
this.height = height.get();
}
MemoryUtil.memAllocInt(1) and ByteBuffer.allocateDirect(4).asIntBuffer() works as well.
1 - I downloaded tesdata on the git hub https://github.com/tesseract-ocr/tessdata
2 - Extract the folder and passed the path to the Tesseract class
3 - When running the application the following error is displayed
Extract the folder and passed the path to the Tesseract class
When running the application the following error is displayed
Code snippet executed
public class TesseractOcrTest {
private final String tesseractPath = "/home/tessdata/";
#Test
public void shouldReturnTrueIfRunOcrEquals() throws Exception {
String result = new TesseractOcr(tesseractPath).runOcr("bw_HighResolution_en.jpeg").trim();
assertEquals(
"Optical Character Recognition in Java\nis made easy with the help of Tesseract", result);
}
}
Error
Error: Illegal Parameter specification!
"Fatal error encountered!" == NULL:Error:Assert failed:in file globaloc.cpp, line 75
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f52a582d69b, pid=8957, tid=8966
#
# JRE version: OpenJDK Runtime Environment (11.0.7+10) (build 11.0.7+10-post-Ubuntu-2ubuntu218.04)
# Java VM: OpenJDK 64-Bit Server VM (11.0.7+10-post-Ubuntu-2ubuntu218.04, mixed mode, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C [libtesseract.so.4+0x25969b] ERRCODE::error(char const*, TessErrorLogCode, char const*, ...) const+0x16b
Note: When I change the path from tesdata to the OS installation path (private final String tesseractPath = "/usr/share/tesseract-ocr/4.00/tessdata/";) I can do it perfectly. It just doesn't work if I point to the tesdata downloaded from the git hub.
What am I doing wrong? When downloaded from github do you need to do any more configuration?
You've probably used incompatible language data. For the current Tesseract verion, use tessdata_best or tessdata_fast, which comes with Linux distros. (You can verify by checking the file size.)
https://github.com/tesseract-ocr
Make sure you have installed only one version of tesseract
Fist check with version of tesseract you used (installed). Use the latest version (4.x or 5 alpha)
Test OCR with tesseract executable instead of wrapper - it can provide more information for finding problem.
This question is very similar to this one however it's on Linux ARM ( Raspberry Pi).
I've compiled OpenCV 4.4.0 from source along with the Java bindings and tried something like this hack (that worked on Windows):
import org.opencv.core.*;
public class CVTest {
public static void main(String[] args) {
System.out.println("setup");
// loading the typical way fails :(
// System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.load("/home/pi/eclipse/CVTest/lib/libopencv_core.so");
////System.load("/home/pi/opencv/build/lib/libopencv_core.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_imgproc.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_imgcodecs.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_img_hash.so");
////System.load("/home/pi/eclipse/CVTest/lib/opencv_core.so");//videoio_ffmpeg440_64.dll
//System.load("/home/pi/eclipse/CVTest/lib/libopencv_videoio.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_photo.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_xphoto.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_flann.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_features2d.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_calib3d.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_phase_unwrapping.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_structured_light.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_xfeatures2d.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_video.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_ximgproc.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_aruco.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_bgsegm.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_bioinspired.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_objdetect.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_face.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_dnn.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_tracking.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_plot.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_ml.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_ml.so");
System.load("/home/pi/eclipse/CVTest/lib/libopencv_text.so");
// crashes here!
System.load("/home/pi/eclipse/CVTest/lib/libopencv_java440.so");
Mat m = Mat.eye(new Size(3,3), CvType.CV_8UC1);
System.out.println("done");
}
}
However, depending on the Raspberry Pi, I get different crashes at the same line, loading libopencv_java440 (after the other dependant libraries have loaded):
On a Raspberry Pi 3B running Raspian stretch I get errors like this one:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGBUS (0x7) at pc=0x6360f644, pid=9730, tid=0x64eba470
#
# JRE version: Java(TM) SE Runtime Environment (8.0_202-b08) (build 1.8.0_202-b08)
# Java VM: Java HotSpot(TM) Client VM (25.202-b08 mixed mode linux-arm )
# Problematic frame:
# C [libopencv_core.so+0x258644] cv::Ptr<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::~Ptr()+0x38
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
--------------- T H R E A D ---------------
Current thread (0x76162400): VMThread [stack: 0x64e3b000,0x64ebb000] [id=9733]
siginfo: si_signo: 7 (SIGBUS), si_code: 1 (BUS_ADRALN), si_addr: 0x7c1f010e
Registers:
r0 = 0x636e6270
r1 = 0x00000000
r2 = 0x000011f8
r3 = 0x7c1f010e
r4 = 0x7c1f00f2
r5 = 0x636e6270
r6 = 0x76ee84ac
r7 = 0x00000001
r8 = 0x6470c600
r9 = 0x000003ec
r10 = 0x000003ec
fp = 0x64eb9c0c
r12 = 0x76fa4ce4
sp = 0x64eb9be8
lr = 0x76ddadd4
pc = 0x6360f644
cpsr = 0x20000010
Top of Stack: (sp=0x64eb9be8)
0x64eb9be8: 76ee8000 00000000 76ee84ac 76ddadd4
0x64eb9bf8: 76129d7c 76ddae34 00000000 76635d7c
0x64eb9c08: 64eb9c2c 768ac3dc 76162270 63736954
0x64eb9c18: 76940000 76129988 76129990 76129d7c
0x64eb9c28: 64eb9ca4 768aaa54 7696a050 76942d14
0x64eb9c38: 64eb9ca4 767f8084 00000000 00000000
0x64eb9c48: 8c365cd8 00000000 76909901 76966044
0x64eb9c58: 76163208 00000000 00000000 7696a050
Instructions: (pc=0x6360f644)
0x6360f624: 0a00000d e59f20c4 e7933002 e3530000
0x6360f634: 0a00000b e284301c ee070fba e1932f9f
0x6360f644: e2421001 e1830f91 e3500000 1afffffa
0x6360f654: e3520001 ee070fba 0a00000f e1a00005
Register to memory mapping:
r0 = 0x636e6270
On a Raspberry Pi ZeroW also running Raspian Stretch I a beefy log: example.
Any tips on getting OpenCV Java bindings to work on arvm6/armv7 CPUs ?
Update
Thanks to the comment from #Catree I've ran the tests as well.
As you can see in opencv_cpp_tests.txt mosts tests run, excluding ones where asset loading is required (Must've botched running the asset part).
I did try running the Java tests as well, however I'm missing something obvious because the java.library.path argument I pass to the lib folder containing opencv's shared libraries doesn't seem to work. You can view the output in opencv_java_tests.txt
I've also tried the old-school 2.4 Introduction to Java Development OpenCV Tutorial specifying the correct java class paths and library path, but got greeted by a segfault :/
java -Djava.library.path=/home/pi/opencv/build/lib -classpath /home/pi/opencv/build/bin/opencv-440.jar:/home/pi/opencv/build/build/jar/SimpleSample.jar SimpleSample -verbose
Segmentation fault
Any hints/tips to progress are greatly appreciated
Update 2
Following #moyeen52's advice I've compiled OpenCV static libs (-DBUILD_SHARED_LIBS=OFF) and noticed libopencv_java.so goes from 2.1MB to 31MB.
Unfortunately I still get the same segfault :(
I also had a look at the other post which unfortunately doesn't apply as OpenCV compiles libopencv_java440.so already (no need to rename).
Update 3
To ease testing for anyone out there with a Raspberry PI 3 B+ I've uploaded the following:
HelloCV.tar.gz: contains Hello.java (which simply tried to load the library, create a Mat and print it), opencv-440.jar, libopencv_java440.so (static build) and compile.sh and run.sh which should call javac/java with the right arguments, locally referencing the java and c++ libraries.
opencv440_static_rpi3b.tar.gz: static library build
opencv440_shared_rpi3b.tar.gz: shared library build
Additionally I will try recompiling without libatomic nor NEON and VPF3 CPU optimisations and will post updates
Your advice/tips are very much appreciated ! Thank you
Thank you everyone for the comments: they have been instrumental in narrowing down the issue and finding a solution.
The c++ errors might hava been due to the difference between C++ compilers (and support for c++ 11 or higher). Although I found a few resources on updating g++ (from 6.3.0 to 8.3.0) I didn't want to risk running into other issues.
I've used completely fresh installs of Raspian OS (Buster) for each system (PiZeroW (armv6) and Pi3B+ (armv7)) which worked with no issues at all. Additionally I've used OpenJDK 8 instead of 11 for my project needs.
I have stored prebuild binaries (full contents of the install folder) here:
opencv_440_pi0w.tar.gz -> compiled on Raspberry Pi Zero W
opencv_440_pi3b.tar.gz -> compiled on Raspberry Pi 3 B+
opencv_440_pi4.tar.gz -> compiled on Raspberry Pi 4
Additionally, there are minimal zips for the java wrapper with a Hello world test and compile/run bash scripts:
HelloCVPI0W.tar.gz for armv6: tested on Raspberry Pi Zero
HelloCVPI3B+.tar.gz for armv7: tested on Raspberry Pi 3 B+
HelloCVPI4.tar.gz for armv7: tested on Raspberry Pi 4
(Note the Java wrapper is compiled with OpenJDK 8)
I'm interfacing with a native Fortran library (physics) from Java/Scala using JNA, invoked using the Apache Spark distributed computing framework.
The following reports are produced using my library /opt/MYORG/hdd/usr/local/lib/mylib.so compiled with ifort and debug compiler options
-shared -fPIC -save -g -check all -fpe0 -traceback -static -static-intel -Bstatic
My executors crash from time to time because of a SIGSEGV, indicated by the JVM error-Report:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fea0f490700, pid=33080, tid=140647778658048
#
# JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C 0x00007fea0f490700
The full report is uploaded here: https://www.amazon.com/clouddrive/share/GDqXyIRNVkY86XYCXkorjiuE4bZm4AmnNWllXBhMVmk?encoding=UTF8&mgh=1&ref=cd_ph_share_link_copy
I managed to create a core-dump which I analyzed with
gdb /usr/java/jdk1.8.0_60/bin/java core.33080
(gdb) bt
#0 0x00007fed0a04f1d7 in raise () from /usr/lib64/libc.so.6
#1 0x00007fed0a0508c8 in abort () from /usr/lib64/libc.so.6
#2 0x00007fed0995b6b5 in os::abort(bool) () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#3 0x00007fed09af9bf3 in VMError::report_and_die() () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#4 0x00007fed09960edf in JVM_handle_linux_signal () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#5 0x00007fed09957673 in signalHandler(int, siginfo*, void*) () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#6 <signal handler called>
#7 0x00007fea0f490700 in ?? ()
#8 0x00007fed0a7fcbc2 in __nptl_deallocate_tsd () from /usr/lib64/libpthread.so.0
#9 0x00007fed0a7fcdd3 in start_thread () from /usr/lib64/libpthread.so.0
#10 0x00007fed0a11173d in clone () from /usr/lib64/libc.so.6
I further analyzed the core with
thread apply all bt full
(The output can be found here: https://www.amazon.com/clouddrive/share/ZUmv6GEM2oJ0MCCqfnNEs2OOateJVGnhnxoHsJnbvBV?ref_=cd_ph_share_link_copy)
But I don't see any thread currently being in my own (probably faulty) library mylib.so, all the threads seem to be waiting. Nothing so far points me to the fact that mylib.so is causing the SIGSEGV, but If I replace the call to mylib.so with a Mock in my code (i.e. no actual native call), no SIGSEGV appear, therefore I conclude that the problem must be in the JNA call to my native library.
So far I tried the following hints: https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors with no success
Can someone help my to find the cause of the above SIGSEGV?
This kind of bugs are quite nasty ones. You can try to apply following pattern:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo015
In this approach you can "catch" SIGSEGV inside your code. Then, you can try to get backtrace using backtrace function:
void *array[100];
size_t size;
size = backtrace (array, 100);
backtrace_symbols_fd (array, size, STDOUT_FILENO);
Please note that you shouldn't do too much inside signal handler.
Then, if you have luck you will be able to spot what was the cause of the issue.
Another approach is to actually debug JVM using gdb and see what happens there.
You can find sample of JNI debugging here:
http://www.owsiak.org/?p=2095
or here:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNoD001
or here:
https://youtu.be/8Cjeq4l5COU
As already advised, try enabling bounds checks inside Fortran code. Sometimes it helps.
I hope that it will help.
Have fun with JNI/JNA.
I'm trying to make JCEF to work in a swingNode in a simple JavaFX Application
public class MainApp extends Application {
#Override
public void start(Stage stage) throws Exception {
SwingNode swingNode = new SwingNode();
SwingUtilities.invokeAndWait(() -> {
String startURL = "https://www.google.com/";
boolean useOSR = OS.isLinux();
boolean isTransparent = false;
CefSettings settings = new CefSettings();
settings.windowless_rendering_enabled = useOSR;
CefApp cefApp_ = CefApp.getInstance(settings);
CefClient client_ = cefApp_.createClient();
CefBrowser browser_ = client_.createBrowser(startURL, useOSR, isTransparent);
Component browerUI_ = browser_.getUIComponent();
JPanel panel = new JPanel();
panel.setSize(800, 600);
panel.add(browerUI_, BorderLayout.CENTER);
swingNode.setContent(panel);
});
stage.setScene(new Scene(new javafx.scene.Group(swingNode)));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
I'm getting a fatal error at client_.createBrowser(startURL, useOSR, isTransparent);
initialize on Thread[AWT-EventQueue-0,6,main] with library path /path/to/jcef/lib/linux64
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f3d07fced50, pid=22843, tid=0x00007f3ca5991700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_111-b14) (build 1.8.0_111-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.111-b14 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C [ld-linux-x86-64.so.2+0x9d50]
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /path/to/jcef-javafx-maven/hs_err_pid22843.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
however, the provided JCEF awt test examples runs perfectly.
JCEF Version = 3.2840.147
CEF Version = 3.2840.1511
Chromium Version = 54.0.2840.59
Oracle JDK version = 1.8.0_111
edit1: digging into the jcef java code, the fatal error happens at CefBrowserOsr.java line 134
private void createGLCanvas() {
GLProfile glprofile = GLProfile.getMaxFixedFunc(true); // here
edit2: error log hs_err_pid.log content.
Upgrading to JOGL 2.3.2 and rebuilding JCEF again partially fixes the problem (no jvm crash happens anymore)
however, it seems that the SwingNode would not render a very complicated stuff like a GLCanvas, reference.